From 779208e017ffda39b5a23482bd12a5c5519dc0b1 Mon Sep 17 00:00:00 2001 From: lucii7vel <33035261+lucii7vel@users.noreply.github.com> Date: Wed, 29 May 2024 07:29:56 -0700 Subject: [PATCH] [python/be] translate (#4963) --- be-by/python-by.html.markdown | 1136 +++++++++++++++++++++++++++++++++ 1 file changed, 1136 insertions(+) create mode 100644 be-by/python-by.html.markdown diff --git a/be-by/python-by.html.markdown b/be-by/python-by.html.markdown new file mode 100644 index 00000000..f16443b6 --- /dev/null +++ b/be-by/python-by.html.markdown @@ -0,0 +1,1136 @@ +--- +language: Python +contributors: + - ["Louie Dinh", "http://pythonpracticeprojects.com"] + - ["Steven Basart", "http://github.com/xksteven"] + - ["Andre Polykanine", "https://github.com/Oire"] + - ["Zachary Ferguson", "http://github.com/zfergus2"] + - ["evuez", "http://github.com/evuez"] + - ["Rommel Martinez", "https://ebzzry.io"] + - ["Roberto Fernandez Diaz", "https://github.com/robertofd1995"] + - ["caminsha", "https://github.com/caminsha"] + - ["Stanislav Modrak", "https://stanislav.gq"] + - ["John Paul Wohlscheid", "https://gitpi.us"] +translators: + - ["lucii7vel", "https://https://github.com/lucii7vel"] +filename: learnpython-by.py +lang: be-by +--- +Python быў створаны Гвіда ван Росумам у пачатку 90-х. Цяпер гэта адна з +самыя папулярных моў праграмавання. Я закахаўся ў Python за яго +сінтаксічную празрыстасць. Гэта літаральна выканальны псеўдакод. + +```python +# Аднарадковыя каментарыі пачынаюцца знакам рашоткі. + +""" Шматрадковыя каментарыі можна + рабіць выкарыстоўваючы тры ", яны часта + выкарыстоўваюцца ў якасці дакументацыі. +""" + +#################################################### +## 1. Прымітыўныя тыпы даных і аператары. +#################################################### + +# Лічбы +3 # => 3 + +# Відавочныя матэматычныя аперацыі +1 + 1 # => 2 +8 - 1 # => 7 +10 * 2 # => 20 +35 / 5 # => 7.0 + +# Вынік цэлалікавага дзялення акругляецца як для пазітыўных, +# так і для негатыўных значэнняў. +5 // 3 # => 1 +-5 // 3 # => -2 + +# Працуе таксама на лічбах з плаваючай кропкай. +5.0 // 3.0 # => 1.0 +-5.0 // 3.0 # => -2.0 + +# Вынік дзялення — заўсёды лічба з плаваючай кропкай. +10.0 / 3 # => 3.3333333333333335 + +# Дзяленне па модулю +7 % 3 # => 1 +# У выніку i % j атрымаецца значэнне са знакам j +-7 % 3 # => 2 + +# Узвядзенне ў ступень +2**3 # => 8 + +# Прыярытэт аперацый праз дужкі +1 + 3 * 2 # => 7 +(1 + 3) * 2 # => 8 + +# Лагічныя значэнні з'яўляюцца прымітывамі +# (Звярніце ўвагу на рэгістр) +True # => True +False # => False + +# Адмаўленне праз not +not True # => False +not False # => True + +# Лагічныя аператары +# Звярніце ўвагу, "and" і "or" чуллівыя да рэгістра +True and False # => False +False or True # => True + +# True і False на самай справе 1 і 0, толькі з іншымі ключавымі словамі. +True + True # => 2 +True * 8 # => 8 +False - 5 # => -5 + +# Параўнальныя аператары звяртаюцца да лічбавых значэнняў True і False. +0 == False # => True +2 > True # => True +2 == True # => False +-5 != False # => True + +# None, 0 і пустыя радкі/спісы/слоўнікі/картэжы/мноства адпавядаюць False. +# Усе іншыя значэнні адпавядаюць True. +bool(0) # => False +bool("") # => False +bool([]) # => False +bool({}) # => False +bool(()) # => False +bool(set()) # => False +bool(4) # => True +bool(-6) # => True + +# Выкарыстоўванне лагічных аператараў на цэлалікавых значэннях ператварае +# іх у boolean для вылічэнняў, але вяртае значэнне іх зыходнага тыпу. +# Не блытайце з bool(int) і пабітавымі and/or (&, |). +bool(0) # => False +bool(2) # => True +0 and 2 # => 0 +bool(-5) # => True +bool(2) # => True +-5 or 0 # => -5 + +# Роўнасць == +1 == 1 # => True +2 == 1 # => False + +# Няроўнасць != +1 != 1 # => False +2 != 1 # => True + +# Больш параўнанняў +1 < 10 # => True +1 > 10 # => False +2 <= 2 # => True +2 >= 2 # => True + +# Праверка значэння на ўваход у дыяпазон +1 < 2 and 2 < 3 # => True +2 < 3 and 3 < 2 # => False +# Звязванне выглядае прыгажэй +1 < 2 < 3 # => True +2 < 3 < 2 # => False + +# (is супраць ==) is правярае, ці спасылаюцца дзве пераменныя на адзін і той жа +# аб'ект, а == правярае, ці маюць дзве пераменныя аднолькавыя значэнні. +a = [1, 2, 3, 4] # a спасылаецца на новы спіс [1, 2, 3, 4] +b = a # b спасылаецца туды ж, куды і a +b is a # => True, a і b спасылаюцца на адзін і той жа аб'ект +b == a # => True, аб'екты a і b аднолькавыя +b = [1, 2, 3, 4] # b спасылаецца на новы спіс [1, 2, 3, 4] +b is a # => False, a і b спасылаюцца на розныя аб'екты +b == a # => True, аб'екты a і b аднолькавыя + +# Радкі ствараюцца праз " ці ' +"Гэта радок." +'Гэта таксама радок.' + +# Радкі можна складваць +"Вітаю, " + "свет!" # => "Вітаю, свет!" +# Радковыя літаралы (але не пераменныя) магчыма злучаць без выкарыстоўвання '+' +"Вітаю, " "свет!" # => "Вітаю, свет!" + +# Радок можна успрымаць як спіс сімвалаў +"Вітаю, свет"[0] # => 'В' + +# Ёсць магчымасць знайсці даўжыню радка +len("Гэта радок") # => 10 + +# З версіі Python 3.6 магчыма выкарыстоўваць f-радкі +# або фарматаваныя радковыя літаралы. +name = "Рэйко" +f"Яна сказала, што яе завуць {name}." # => "Яна сказала, што яе завуць Рэйко" +# Любы дзейны Python-выраз унутры гэтых дужак вяртаецца ў радок. +f"Даўжыня {name} — {len(name)} сімвалаў." # => "Даўжыня Рэйко — 5 сімвалаў." + +# None — гэта аб'ект +None # => None + +# Не выкарыстоўвайце знак роўнасці '==' для параўнання аб'ектаў з None. +# Замест гэтага карыстайцеся 'is'. Ён правярае аб'екты на ідэнтычнасць. +"etc" is None # => False +None is None # => True + +#################################################### +## 2. Пераменныя і калекцыі +#################################################### + +# У Python ёсць функцыя print +print("Я Python. Рады бачыць!") # => Я Python. Рады бачыць! + +# Па змаўчанні print таксама пераводзіць на новы радок у канцы. +# Выкарыстоўвайце апцыянальны аргумент end каб змяніць канцоўку радка. +print("Вітаю, свет", end="!") # => Вітаю, свет! + +# Просты спосаб атрымаць уваходныя даныя з кансолі +input_string_var = input("Увядзіце даныя: ") # Вяртае даныя ў якасці радка + +# Ніякіх аб'яўленняў, толькі прызначэнні пераменных. +# Пераменныя заведзена называць у стылі snake_case. +some_var = 5 +some_var # => 5 + +# Звяртанне да непрызначаннай пераменнай прыводзіць да выключэння. +# Падрабязнасці пра апрацоўку выключэнняў у раздзеле "Паток кіравання". +some_unknown_var # Выкідвае NameError + +# if можа быць выкарыстаны ў якасці выражэння +# Эквівалент цернарнага аператара '?:' з C +"Так!" if 0 > 1 else "Не!" # => "Не!" + +# Спісы захоўваюць паслядоўнасці +li = [] +# Вы можаце стварыць запоўнены спіс +other_li = [4, 5, 6] + +# Дадаць нешта ў канец спіса праз append +li.append(1) # li цяпер [1] +li.append(2) # li цяпер [1, 2] +li.append(4) # li цяпер [1, 2, 4] +li.append(3) # li цяпер [1, 2, 4, 3] +# Выдаліць з канца праз pop +li.pop() # => 3 li цяпер [1, 2, 4] +# Пакладзём назад +li.append(3) # li цяпер зноў [1, 2, 4, 3] + +# Звяртайцеся да спіса як да звычайнага масіву +li[0] # => 1 +# Зварот да апошняга элемента +li[-1] # => 3 + +# Зварот за межы спіса выкідвае IndexError +li[4] # выклідвае IndexError + +# Магчыма звяртацца да дыяпазонаў праз адсячэнні. +# Пачатковы індэкс уключаецца ў дыяпазон, а канчатковы не +# (матэматыкі сярод вас ведаюць гэта як напаўадкрыты адцінак). +li[1:3] # Вярнуць спіс з індэкса 1 па 3 => [2, 4] +li[2:] # Вярнуць спіс з індэкса 2 => [4, 3] +li[:3] # Вярнуць спіс да індэкса 3 => [1, 2, 4] +li[::2] # Вярнуць спіс, абіраючы элементы з крокам 2 => [1, 4] +li[::-1] # Вярнуць спіс у адваротным парадку => [3, 4, 2, 1] +# Выкарыстоўвайце іх у рознай камбінацыі, каб ствараць лепшыя адсячэнні +# li[пачатак:канец:крок] + +# Зрабіць копію глыбінёй у адзін слой выкарыстоўваючы адсячэнні +li2 = li[:] # => li2 = [1, 2, 4, 3] але (li2 is li) верне false. + +# Выдаліць элемент са спіса па пазіцыі праз "del" +del li[2] # li цяпер [1, 2, 3] + +# Выдаліць першае знойдзенае значэнне +li.remove(2) # li цяпер [1, 3] +li.remove(2) # Выкідвае ValueError, бо ў спісе няма элемента са значэннем 2 + +# Уставіць элемент па дадзенаму індэксу +li.insert(1, 2) # li цяпер зноў [1, 2, 3] + +# Атрымаць індэкс першага элемента з дадзеным значэннем +li.index(2) # => 1 +li.index(4) # Выкідвае ValueError, бо ў спісе няма элемента са значэннем 4 + +# Магчыма складваць спісы. +# Заўвага: значэнні li і other_li не змяняюцца. +li + other_li # => [1, 2, 3, 4, 5, 6] + +# Аб'яднанне спісаў праз "extend()" +li.extend(other_li) # li цяпер [1, 2, 3, 4, 5, 6] + +# Праверка на наяўнасць элемента ў спісе праз "in" +1 in li # => True + +# Атрымаць даўжыню спіса праз "len()" +len(li) # => 6 + + +# Картэжы падобныя на спісы, але не змяняюцца +tup = (1, 2, 3) +tup[0] # => 1 +tup[0] = 3 # Выкідвае TypeError + +# Звярніце ўвагу, што картэжы даўжыні 1 павінны мець коску пасля +# апошняга элемента, але картэжы іншай даўжыні, нават 0, не. +type((1)) # => +type((1,)) # => +type(()) # => + +# Большасць аперацый для спісаў працуюць таксама на картэжах +len(tup) # => 3 +tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) +tup[:2] # => (1, 2) +2 in tup # => True + +# Вы можаце распакоўваць картэжы (або спісы) у пераменныя +a, b, c = (1, 2, 3) # a цяпер 1, b цяпер 2 і c цяпер 3 +# Таксама ёсць пашыраная распакоўка +a, *b, c = (1, 2, 3, 4) # a цяпер 1, b цяпер [2, 3] і c цяпер 4 +# Картэжы ствараюцца па змаўчанні, калі апусціць дужкі +d, e, f = 4, 5, 6 # картэж 4, 5, 6 распакоўваецца ў d, e, f, +# адпаведна, d = 4, e = 5 і f = 6. +# Цяпер паглядзіце, як лёгка абмяняць значэнні дзвюх пераменных +e, d = d, e # d цяпер 5, e цяпер 4 + + +# Слоўнікі змяшчаюць пары ключ/значэнне +empty_dict = {} +# Так выглядае папярэдне запоўнены слоўнік +filled_dict = {"адзін": 1, "два": 2, "тры": 3} + +# Звярніце ўвагу, што ключы ў слоўніках павінны быць нязменных тыпаў. Гэта для +# таго, каб пераканацца, што ключ заўсёды створыць аднолькавы хэш для пошуку. +# У нязменныя тыпы ўваходзяць цэлалікавыя значэнні, +# значэнні з плаваючай кропкай, радкі і картэжы. +invalid_dict = {[1,2,3]: "123"} # => Вікідвае TypeError: unhashable type: 'list' +valid_dict = {(1,2,3):[1,2,3]} # Значэнні, аднак, могуць быць любых тыпаў. + +# Пошук значэнняў праз [] +filled_dict["адзін"] # => 1 + +# Атрымаць усе ключы ў якасці itterable-аб'екта праз "keys()". Нам трэба +# абгарнуць вызаў у list(), каб ператварыць вынік у спіс. Паразмаўляем аб +# гэтым пазней. Заўвага, для версій Python, ніжэйшых за 3.7, парадак ключоў +# слоўніка не гарантуецца, вашыя вынікі могуць не адпавядаць прыкладам ніжэй. +# Аднак, з версіі Python 3.7, элементы слоўніка захоўваюць парадак, у якім яны +# былі ўстаўлены. +list(filled_dict.keys()) # => ["тры", "два", "адзін"] для Python <3.7> +list(filled_dict.keys()) # => ["адзін", "два", "тры"] для Python 3.7+ + + +# Атрымаць усе значэнні ў якасці itterable-аб'екта праз "values()". Зноў жа, +# нам трэба абгарнуць вызаў у list(), каб атрымаць спіс. Тая ж заўвага пра +# парадак, што і вышэй. +list(filled_dict.values()) # => [3, 2, 1] для Python <3.7 +list(filled_dict.values()) # => [1, 2, 3] для Python 3.7+ + +# Праверка на наяўнасць ключа ў слоўніку праз "in" +"адзін" in filled_dict # => True +1 in filled_dict # => False + +# Пошук неіснуючага ключа выкідвае KeyError +filled_dict["чатыры"] # KeyError + +# Выкарыстоўвайце метад "get()", каб пазбегнуць KeyError +filled_dict.get("адзін") # => 1 +filled_dict.get("чатыры") # => None +# get() падтрымлівае прадвызначаны аргумент, калі значэнне адсутнічае ў слоўніку +filled_dict.get("адзін", 4) # => 1 +filled_dict.get("чатыры", 4) # => 4 + +# "setdefault()" устаўляе ў слоўнік толькі калі дадзенага ключа не існуе +filled_dict.setdefault("пяць", 5) # filled_dict["пяць"] цяпер 5 +filled_dict.setdefault("пяць", 6) # filled_dict["пяць"] усё яшчэ 5 + +# Дадаванне ў слоўнік +filled_dict.update({"чатыры":4}) +# => {"адзін": 1, "два": 2, "тры": 3, "чатыры": 4} +filled_dict["чатыры"] = 4 # іншы спосаб дадаць у слоўнік + +# Выдаленне ключоў са слоўніка праз del +del filled_dict["адзін"] # выдаляе ключ "адзін" з запоўненага слоўніка + +# З версіі Python 3.5 таксама існуюць дадатковыя спосабы распакоўкі +{'a': 1, **{'b': 2}} # => {'a': 1, 'b': 2} +{'a': 1, **{'a': 2}} # => {'a': 2} + + + +# Мноства змяшчаюць... Ну, мноства +empty_set = set() +# Ініцыялізваць мноства з кучы значэнняў +some_set = {1, 1, 2, 2, 3, 4} # some_set цяпер {1, 2, 3, 4} + +# Адпаведна ключам слоўніка, элементы мноства павінны быць нязменнымі +invalid_set = {[1], 1} # => Выкідвае TypeError: unhashable type: 'list' +valid_set = {(1,), 1} + +# Дадаць яшчэ адзін элемент у мноства +filled_set = some_set +filled_set.add(5) # filled_set цяпер {1, 2, 3, 4, 5} +# Мноства не змяшчаюць паўторных элементаў +filled_set.add(5) # застаецца ранейшым {1, 2, 3, 4, 5} + +# Перасячэнне мностваў праз & +other_set = {3, 4, 5, 6} +filled_set & other_set # => {3, 4, 5} + +# Аб'яднанне мностваў праз | +filled_set | other_set # => {1, 2, 3, 4, 5, 6} + +# Рознасць мностваў праз - +{1, 2, 3, 4} - {2, 3, 5} # => {1, 4} + +# Сіметрычная рознасць мностваў праз ^ +{1, 2, 3, 4} ^ {2, 3, 5} # => {1, 4, 5} + +# Праверыць, ці з'яўляецца мноства злева надмноствам мноства справа +{1, 2} >= {1, 2, 3} # => False + +# Праверыць, ці з'яўляецца мноства злева падмноствам мноства справа +{1, 2} <= {1, 2, 3} # => True + +# Праверка на наяўнасць у мностве праз in +2 in filled_set # => True +10 in filled_set # => False + +# Зрабіць копію глыбінёй у адзін слой +filled_set = some_set.copy() # filled_set цяпер {1, 2, 3, 4, 5} +filled_set is some_set # => False + + +#################################################### +## 3. Паток кіравання і ітэрабельныя аб'екты +#################################################### + +# Давайце зробім пераменную +some_var = 5 + +# Так выглядае інструкцыя if. Водступы маюць значэнне ў Python! +# Заведзена выкарыстоўваць чатыры прабелы, не табуляцыю. +# Гэта выводзіць "some_var меньшая за 10" +if some_var > 10: + print("some_var цалкам большая за 10.") +elif some_var < 10: # гэты elif неабавязковы. + print("some_var меньшая за 10.") +else: # гэта таксама неабавязкова. + print("some_var насамрэч 10.") + + +""" +Ітэраванне спісаў праз цыкл for +выводзіць: + сабакі — млекакормячыя + каты — млекакормячыя + мышы — млекакормячыя +""" +for animal in ["сабакі", "каты", "мышы"]: + # Вы можаце выкарыстоўваць format() для ўводу фарматаваных радкоў + print("{} — млекакормячыя".format(animal)) + +""" +"range(number)" вяртае ітэрабельны аб'ект з лічбаў +ад 0 да дадзенай лічбы (не ўключна) +выводзіць: + 0 + 1 + 2 + 3 +""" +for i in range(4): + print(i) + +""" +"range(lower, upper)" вяртае ітэрабельны аб'ект з лічбаў +ад ніжэйшай(lower) да вышэйшай(upper) лічбы +выводзіць: + 4 + 5 + 6 + 7 +""" +for i in range(4, 8): + print(i) + +""" +"range(lower, upper, step)" вяртае ітэрабельны аб'ект з лічбаў +ад ніжэйшай да вышэйшай лічбы з дадзеным крокам. Калі крок не +вызначаны, прадвызначаным значэннем з'яўляецца 1 +выводзіць: + 4 + 6 +""" +for i in range(4, 8, 2): + print(i) + +""" +Прайсці цыклам праз спіс, каб атрымаць індэкс і значэнне кожнага элемента: + 0 сабака + 1 кот + 2 мыш +""" +animals = ["сабака", "кот", "мыш"] +for i, value in enumerate(animals): + print(i, value) + +""" +Цыклы while працуюць пакуль умова не парушана +prints: + 0 + 1 + 2 + 3 +""" +x = 0 +while x < 4: + print(x) + x += 1 # Скарачэнне x = x + 1 + +# Апрацоўка выключэнняў праз блок try/except +try: + # Выкарыстоўвайце "raise" каб выкінуць памылку + raise IndexError("Гэта памылка індэкса") +except IndexError as e: + pass # Не рабіце так, забяспечце аднаўленне. +except (TypeError, NameError): + pass # Некалькі выключэнняў можна апрацоўваць сумесна. +else: # Неабавязковая частка блока try/except. Павінна быць + # пасля ўсіх блокаў except. + print("Усё добра!") # Выконваецца толькі калі код унутры try не выкідвае + # выключэнняў +finally: # Выконваецца пры ўсіх абставінах. + print("Тут можна пачысціць рэсурсы") + +# Замест try/finally для ачысткі рэсурсаў магчыма выкарыстоўваць with +with open("myfile.txt") as f: + for line in f: + print(line) + +# Запіс у файл +contents = {"aa": 12, "bb": 21} +with open("myfile1.txt", "w") as file: + file.write(str(contents)) # запісвае радок у файл + +import json +with open("myfile2.txt", "w") as file: + file.write(json.dumps(contents)) # запісвае аб'ект у файл + +# Reading from a file +with open('myfile1.txt', "r") as file: + contents = file.read() # чытае радок з файла +print(contents) +# выводзіць: {"aa": 12, "bb": 21} + +with open('myfile2.txt', "r") as file: + contents = json.load(file) # чытае json аб'ект з файла +print(contents) +# выводзіць: {"aa": 12, "bb": 21} + + +# Python прапануе фундаментальную абстракцыю +# пад назвай Iterable ("ітэрабельны аб'ект" далей). +# Ітэрабельны аб'ект — гэта аб'ект, які можна разглядаць як паслядоўнасць. +# Аб'ект, які вяртаецца функцыяй range, з'яўляецца ітэрабельным. + +filled_dict = {"адзін": 1, "два": 2, "тры": 3} +our_iterable = filled_dict.keys() +print(our_iterable) # => dict_keys(['адзін', 'два', 'тры']). Гэта аб'ект, + # які рэалізуе інтэрфейс Iterable. + +# Мы можам прайсці па яму цыклам +for i in our_iterable: + print(i) # Выводзіць адзін, два, тры + +# Аднак, да элементаў нельга звяртацца па індэксу +our_iterable[1] # Выкідвае TypeError + +# Ітэрабельны аб'ект ведае, як стварыць ітэратар +our_iterator = iter(our_iterable) + +# Наш ітэратар з'яўляецца аб'ектам, які можа запамінаць +# стан падчас нашага праходу праз яго. +# Мы можам атрымаць наступны аб'ект з дапамогаю "next()" +next(our_iterator) # => "адзін" + +# Ён утрымлівае стан, пакуль мы ітэруем +next(our_iterator) # => "два" +next(our_iterator) # => "тры" + +# Калі ітэратар вярнуў усе дадзеныя, ён выкідвае выключэнне StopIteration +next(our_iterator) # Выкідвае StopIteration + +# Мы таксама можам прайсці па яму цыклам, +# насамрэч, "for" ускосна гэта і робіць +our_iterator = iter(our_iterable) +for i in our_iterator: + print(i) # Выводзіць адзін, два, тры + +# Вы можаце захапіць усе элементы ітэрабельнага аб'екта або ітэратара +# праз вызаў list() +list(our_iterable) # => Вяртае ["адзін", "два", "тры"] +list(our_iterator) # => Вяртае [], бо стан захоўваецца + + +#################################################### +## 4. Функцыі +#################################################### + +# Выкарыстоўвайце "def" для стварэння новых функцый +def add(x, y): + print("x = {}, а y - {}".format(x, y)) + return x + y # Вяртайце значэнні праз return + +# Вызаў функцый з параметрамі +add(5, 6) # => выводзіць "x = 5, а y = 6" і вяртае 11 + +# Таксама магчыма вызываць функцыі з найменнымі аргументамі +add(y=6, x=5) # Найменныя аргументы можна выкарыстоўваць у любым парадку + +# Вы можаце вызначыць функцыю, якая прымае зменлівую колькасць +# пазіцыйных аргументаў +def varargs(*args): + return args + +varargs(1, 2, 3) # => (1, 2, 3) + +# Таксама, вы можаце вызначаць функцыі, якія прымаюць зменлівую колькасць +# найменных аргументаў +def keyword_args(**kwargs): + return kwargs + +# Давайце вызавем яе і паглядзім, што будзе +keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"} + + +# Вы можаце выкарыстоўваць два спосабы адначасова, калі хочаце +def all_the_args(*args, **kwargs): + print(args) + print(kwargs) +""" +all_the_args(1, 2, a=3, b=4) выводзіць: + (1, 2) + {"a": 3, "b": 4} +""" + +# Вызываючы функцыі, вы можаце зрабіць адваротнае args/kwargs! +# Выкарыстоўвайце * для разгортвання пазіцыйных аргументаў (картэжаў) +# і ** для разгортвання найменных аргументаў (слоўнікаў) +args = (1, 2, 3, 4) +kwargs = {"a": 3, "b": 4} +all_the_args(*args) # адпавядае: all_the_args(1, 2, 3, 4) +all_the_args(**kwargs) # адпавядае: all_the_args(a=3, b=4) +all_the_args(*args, **kwargs) # адпавядае: all_the_args(1, 2, 3, 4, a=3, b=4) + +# Вяртанне некалькіх значэнняў (з прызначэннем картэжаў) +def swap(x, y): + return y, x # Вяртае некалькі значэнняў у выглядзе картэжу без дужак. + # (Заўвага: дужкі апускаюцца, але могуць выкарыстоўвацца) + +x = 1 +y = 2 +x, y = swap(x, y) # => x = 2, y = 1 +# (x, y) = swap(x,y) # Зноў жа, выкарыстоўваць дужкі неабавязкова + +# глабальная вобласць +x = 5 + +def set_x(num): + # лакальная вобласць пачынаецца тут + # лакальная пераменная x адрозніваецца ад глабальнай + x = num # => 43 + print(x) # => 43 + +def set_global_x(num): + # global пазначае, што пераменная знаходзіцца ў глабальнай вобласці + global x + print(x) # => 5 + x = num # глабальная пераменная x цяпер 6 + print(x) # => 6 + +set_x(43) +set_global_x(6) +""" +выводзіць: + 43 + 5 + 6 +""" + + +# Python падтрымлівае функцыі першага класа +def create_adder(x): + def adder(y): + return x + y + return adder + +add_10 = create_adder(10) +add_10(3) # => 13 + +# Замыканні ва ўкладзеных функцыях: +# Мы можам выкарыстоўваць ключавое слова nonlocal для працы з пераменнымі +# ўнутры ўкладзенай вобласці, якія не павінны быць аб'яўлены ва ўнутраных +# функцыях. +def create_avg(): + total = 0 + count = 0 + def avg(n): + nonlocal total, count + total += n + count += 1 + return total/count + return avg +avg = create_avg() +avg(3) # => 3.0 +avg(5) # (3+5)/2 => 4.0 +avg(7) # (8+7)/3 => 5.0 + +# Таксама існуюць ананімныя функцыі +(lambda x: x > 2)(3) # => True +(lambda x, y: x ** 2 + y ** 2)(2, 1) # => 5 + +# Існуюць убудаваныя функцыі вышэйшага парадку +list(map(add_10, [1, 2, 3])) # => [11, 12, 13] +list(map(max, [1, 2, 3], [4, 2, 1])) # => [4, 2, 3] + +list(filter(lambda x: x > 5, [3, 4, 5, 6, 7])) # => [6, 7] + +# Для прыгажосці, замест map і filter мы можам выкарыстоўваць спісачныя выразы +# Спісачныя выразы захоўваюць вынік у выглядзе спіса (які сам па сабе можа +# быць укладзеным). +[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] + +# Таксама вы можаце стварыць адпаведныя выразы для мностваў і слоўнікаў +{x for x in 'abcddeef' if x not in 'abc'} # => {'d', 'e', 'f'} +{x: x**2 for x in range(5)} # => {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} + + +#################################################### +## 5. Модулі +#################################################### + +# Вы можаце імпартаваць модулі +import math +print(math.sqrt(16)) # => 4.0 + +# Вы можаце ўзяць дакладныя функцыі з модуля +from math import ceil, floor +print(ceil(3.7)) # => 4 +print(floor(3.7)) # => 3 + +# Вы можаце імпартаваць усе функцыі з модуля. +# Заўвага: не рэкамендуецца так рабіць. +from math import * + +# Вы можаце скарачаць імёны модуляў +import math as m +math.sqrt(16) == m.sqrt(16) # => True + +# Модулі ў Python з'яўляюцца звычайнымі Python файламі. Вы можаце напісаць +# свае і імпартаваць іх. Імя модуля адпавядае імені файла. + +# Вы можаце даведацца, якія функцыі і атрыбуты вызначаны ў модулі +import math +dir(math) + +# Калі ў вас ёсць Python-скрыпт з назвай math.py у той жа папцы, +# што і бягучы скрыпт, файл math.py будзе загружаны замест убудаванага +# Python-модуля. Гэта адбываецца таму, што лакальная папка мае большы +# прыярытэт, чым убудаваныя Python-бібліятэкі. + + +#################################################### +## 6. Класы +#################################################### + +# Мы выкарыстоўваем інструкцыю "class" для стварэння класаў +class Human: + + # Атрыбут класа. Яго першапачатковае значэнне пашыраецца + # паміж усімі экзэмплярамі класа. + species = "H. sapiens" + + # Базавы канструктар, вызываецца пры стварэнні экзэмпляраў класа. + # Звярніце ўвагу, што двайное падкрэсліванне абазначае аб'екты або + # атрыбуты, якія выкарыстоўвае Python, але яны існуюць у прасторах назваў, + # якія кантралюе карыстальнік. Метады(або аб'екты ці атрыбуты), такія як + # __init__, __str__, __repr__ і г.д., называюцца спецыяльнымі метадамі, + # або магічнымі метадамі. Вам не варта ствараць такія імёны самастойна. + def __init__(self, name): + # Прызначэнне аргумента атрыбуту name экзэмпляра класа + self.name = name + + # Ініцыялізацыя ўласцівасці + self._age = 0 # папярэдняе падкрэсліванне абазначае, што ўласцівасць + # "age" створана для ўнутранага выкарыстання, + # але гэта ніяк не кантралюецца, а з'яўляецца + # звычайнай падказкай для іншых распрацоўшчыкаў. + + # Метад экзэмпляра. Усе метады прымаюць "self" у якасці першага аргумента. + def say(self, msg): + print("{name}: {message}".format(name=self.name, message=msg)) + + # Іншы метад экзэмпляра + def sing(self): + return 'ёў... ёў... праверка мікрафона... раз два... раз два...' + + # Метад класа пашыраецца паміж усімі экзэмплярамі. + # Яны вызываюцца з указаннем вызываючага класа ў якасці першага аргумента. + @classmethod + def get_species(cls): + return cls.species + + # Статычны метад вызываецца без спасылкі на клас або экзэмпляр + @staticmethod + def grunt(): + return "*рохкае*" + + # property зусім як гетэр + # гэты дэкаратар ператварае метад age() у аднайменны атрыбут, + # даступны толькі для чытання. + # У Python не трэба пісаць трывіяльныя гетэры і сэтэры, дарэчы. + @property + def age(self): + return self._age + + # Гэта дазваляе ўстанавіць уласцівасць + @age.setter + def age(self, age): + self._age = age + + # Гэта дазваляе выдаліць уласцівасць + @age.deleter + def age(self): + del self._age + + +# Калі інтэрпрэтатар Python чытае зыходны файл, ён выконвае ўвесь код. +# З дапамогай гэтай праверкі, блок кода выконваецца толькі калі модуль +# з'яўляецца асноўнай праграмай. +if __name__ == '__main__': + # Стварэнне экзэмпляра класа + i = Human(name="Ігар") + i.say("вітан") # "Ігар: вітан" + j = Human("Янка") + j.say("вітаю") # "Янка: вітаю" + # i з j з'яўляюцца экзэмплярамі тыпу Human, г.з., яны аб'екты Human + + # Вызаў метаду класа + i.say(i.get_species()) # "Ігар: H. sapiens" + # Змена агульнага атрыбута + Human.species = "H. neanderthalensis" + i.say(i.get_species()) # => "Ігар: H. neanderthalensis" + j.say(j.get_species()) # => "Янка: H. neanderthalensis" + + # Вызаў статычнага метаду + print(Human.grunt()) # => "*рохкае*" + + # Статычны метад магчыма вызваць таксама з экзэмпляра + print(i.grunt()) # => "*рохкае*" + + # Абнавіць уласцівасць для гэтага экзэмпляра + i.age = 42 + # Атрымаць уласцівасць + i.say(i.age) # => "Ігар: 42" + j.say(j.age) # => "Янка: 0" + # Выдаліць уласцівасць + del i.age + # i.age # => гэта выкіне AttributeError + + +#################################################### +## 6.1 Наследаванне +#################################################### + +# Наследаванне дазваляе вызначаць новыя вытворныя класы, якія наследуюць +# метады і пераменныя сваіх базавых класаў. + +# Выкарыстоўваючы клас Human, вызначаны раней, у якасці базавага або +# класа-папярэдніка, мы можам вызначыць вытворны клас Superhero, які наследуе +# пераменныя класа(species, name, age) і метады(sing, grunt) з класа Human, +# але таксама мае свае ўнікальныя ўласцівасці. + +# Каб выкарыстаць перавагі файлавай модульнасці, вы можаце змясціць класы +# ў асобныя файлы, напрыклад, human.py + +# Каб імпартаваць функцыі з іншых файлаў, выкарыстоўвайце наступны фармат +# from "імя-файла-без-пашырэння" import "функцыя-або-клас" + +from human import Human + + +# Пазначце клас-папярэднік ў якасці параметра ў вызначэнні вытворнага класа +class Superhero(Human): + + # Калі вытворнаму класу трэба толькі ўнаследаваць усе вызначэнні + # класа-папярэдніка без мадыфікацый, вы можаце выкарыстаць ключавое + # слова "pass" (і нічога больш), але ў гэтым выпадку яно закаментавана, + # каб мець магчымасць стварыць унікальны клас + # pass + + # Вытворныя класы могуць перавызначыць атрыбуты папярэднікаў + species = 'Суперчалавек' + + # Вытворныя класы аўтаматычна наследуюць канструктары папярэднікаў разам + # з аргументамі, але таксама могуць вызначаць дадатковыя аргументы або + # вызначэнні, і перавызначаць метады, такія як канструктар класа. + # Гэты канструктар наследуе аргумент name з Human + # і дадае superpowers і movie: + def __init__(self, name, movie=False, + superpowers=["суперсіла", "куленепрабівальнасць"]): + + # дадаць дадатковыя атрыбуты класа: + self.fictional = True + self.movie = movie + # сцеражыцеся прадвызначаных значэнняў зменных тыпаў, + # паколькі яны абагульняюцца + self.superpowers = superpowers + + # Функцыя "super" дазваляе атрымаць доступ да метадаў папярэдніка, + # якія былі перавызначаны ў вытворным класе, у гэтым выпадку + # да метаду __init__. + # Вызаў канструктара класа-папярэдніка: + super().__init__(name) + + # перавызначыць метад sing + def sing(self): + return 'Шчучыншчына!' + + # дадаць дадатковы метад экзэмпляра + def boast(self): + for power in self.superpowers: + print("Я маю такую моц, як {pow}!".format(pow=power)) + + +if __name__ == '__main__': + sup = Superhero(name="Клешч") + + # Праверка тыпу экзэмпляра + if isinstance(sup, Human): + print('Я — чалавек') + if type(sup) is Superhero: + print('Я — супергерой') + + # Атрымаць "Парадак Вырашэння Метаду"(Method Resolution Order), які + # выкарыстоўваюць getattr() і super() + # (парадак, у якім адбываецца пошук атрыбутаў або метадаў у класе). + # Гэты атрыбут дынамічны і можа абнаўляцца. + print(Superhero.__mro__) # => (, + # => , ) + + # Вызывае метад папярэдніка, але выкарыстоўвае ўласны атрыбут класа + print(sup.get_species()) # => Суперчалавек + + # Вызывае перавызначаны метад + print(sup.sing()) # => Шчучыншчына! + + # Вызывае метад з Human + sup.say('Лыжка') # => Клешч: Лыжка + + # Вызывае метад, які існуе толькі ўнутры Superhero + sup.boast() # => Я маю такую моц, як суперсіла! + # => Я маю такую моц, як куленепрабівальнасць! + + # Унаследаваны атрыбут класа + sup.age = 31 + print(sup.age) # => 31 + + # Атрыбут, які існуе толькі ўнутры Superhero + print('Я магу атрымаць Оскар? ' + str(sup.movie)) + +#################################################### +## 6.2 Множнае наследаванне +#################################################### + +# Вызначэнне іншага класа +# bat.py +class Bat: + + species = 'рукакрылачка' + + def __init__(self, can_fly=True): + self.fly = can_fly + + # У гэтым класе таксама ёсць метад say + def say(self, msg): + msg = '... ... ...' + return msg + + # І свой уласны метад таксама + def sonar(self): + return '))) ... (((' + +if __name__ == '__main__': + b = Bat() + print(b.say('вітаю')) + print(b.fly) + + +# І вызначэнне яшчэ аднаго класа, які наследуецца ад Superhero і Bat +# superhero.py +from superhero import Superhero +from bat import Bat + +# Вызначыць Batman у якасці вытворнага класа, +# які наследуецца ад Superhero і Bat. +class Batman(Superhero, Bat): + + def __init__(self, *args, **kwargs): + # Звычайна, каб унаследаваць атрыбуты, вам трэба вызваць super: + # super(Batman, self).__init__(*args, **kwargs) + # Аднак, мы маем справу з множным наследаваннем, а super() працуе + # толькі з наступным базавым класам у спісе MRO. + # Таму, замест гэтага мы напрамую вызываем __init__ + # для кожнага з папярэднікаў. + # Выкарыстанне *args і **kwargs дазваляе ахайна перадаць аргументы, + # якія папярэднікі будуць разбіраць слой за слоем. + Superhero.__init__(self, 'ананім', movie=True, + superpowers=['Багаты'], *args, **kwargs) + Bat.__init__(self, *args, can_fly=False, **kwargs) + # перавызначэнне значэння атрыбута name + self.name = 'Сум Афлек' + + def sing(self): + return 'шчу шчу шчу шчу Шчучыншчына!' + + +if __name__ == '__main__': + sup = Batman() + + # Парадак Вырашэння Метаду(MRO) + print(Batman.__mro__) # => (, + # => , + # => , + # => , ) + + # Вызывае метад папярэдніка, але выкарыстоўвае ўласныя атрыбуты + print(sup.get_species()) # => Суперчалавек + + # Вызывае перавызначаны метад + print(sup.sing()) # => шчу шчу шчу шчу Шчучыншчына! + + # Вызывае метад з Human, бо парадак наследавання мае значэнне + sup.say('згодны') # => Сум Афлек: згодны + + # Вызывае метад, які існуе толькі ў другім папярэдніку + print(sup.sonar()) # => ))) ... ((( + + # Унаследаваны атрыбут класа + sup.age = 100 + print(sup.age) # => 100 + + # Унаследаваны атрыбут другога папярэдніка, прадвызначаныя значэнні + # якога былі пераназначаны + print('Я ўмею лятаць? ' + str(sup.fly)) # => Я ўмею лятаць? False + + + +#################################################### +## 7. Дадаткова +#################################################### + +# Генератары дапамагаюць пісаць лянівы код +def double_numbers(iterable): + for i in iterable: + yield i + i + +# Генератары эфектыўна выкарыстоўваюць памяць, таму што загружаюць толькі +# даныя, патрэбныя для апрацоўкі наступнага кроку ітэрацыі. Гэта дазваляе +# ім выконваць аперацыі з вялікімі дыяпазонамі даных, якія ў іншых выпадках +# былі б недапушчальнымі. +# Заўвага: `range` замяняе `xrange` у Python 3. +for i in double_numbers(range(1, 900000000)): # `range` гэта генератар. + print(i) + if i >= 30: + break + +# Адпаведна спісачным выразам, магчыма таксама ствараць генератарныя выразы. +values = (-x for x in [1,2,3,4,5]) +for x in values: + print(x) # выводзіць -1 -2 -3 -4 -5 у кансоль/тэрмінал + +# Таксама вы можаце ператварыць генератарны выраз прама ў спісак. +values = (-x for x in [1,2,3,4,5]) +gen_to_list = list(values) +print(gen_to_list) # => [-1, -2, -3, -4, -5] + + +# Дэкаратары з'яўляюцца формай сінтаксічнага цукру. +# Нягледзячы на дзіўны сінтаксіс, яны робяць код лягчэйшым для прачытання. + +# Абгорткі — адзін з відаў дэкаратараў. +# З іх дапамогай вельмі зручна дадаваць лагіраванне ў існуючыя функцыі без +# неабходнасці іх мадыфікаваць. + +def log_function(func): + def wrapper(*args, **kwargs): + print("Уваход у функцыю", func.__name__) + result = func(*args, **kwargs) + print("Выхад з функцыі", func.__name__) + return result + return wrapper + +@log_function # адпаведнік: +def my_function(x,y): # def my_function(x,y): + return x+y # return x+y + # my_function = log_function(my_function) +# Дэкаратар @log_function кажа, што падчас прачытання вызначэння функцыі +# my_function, яна будзе абгорнута ў log_function. +# Калі вызначэнні функцый доўгія, можа быць цяжка апрацаваць неабгорнутыя +# прызначэнні ў канцы вызначэнняў. + +my_function(1,2) # => "Уваход у функцыю my_function" + # => "3" + # => "Выхад з функцыі my_function" + +# Але ёсць праблема. +# Што калі мы паспрабуем атрымаць якую-небудзь інфармацыю пра my_function? + +print(my_function.__name__) # => 'wrapper' +print(my_function.__code__.co_argcount) # => 0. argcount у выніку 0 таму, што абодва аргументы ў сігнатуры wrapper() з'яўляюцца апцыянальнымі. + +# Таму, што наш дэкаратар адпавядае my_function = log_function(my_function), +# мы замянілі інфармацыю аб my_function інфармацыяй з абгорткі. + +# Выправіць гэта праз functools + +from functools import wraps + +def log_function(func): + @wraps(func) # Гэта гарантуе, што дакументацыйны радок (docstring), імя + # функцыі, спіс аргументаў і інш., капіруюцца ў выніковую + # функцыю замест іх замены інфармацыяй з абгорткі. + def wrapper(*args, **kwargs): + print("Уваход у функцыю ", func.__name__) + result = func(*args, **kwargs) + print("Выхад з функцыі ", func.__name__) + return result + return wrapper + +@log_function +def my_function(x,y): + return x+y + +my_function(1,2) # => "Уваход у функцыю my_function" + # => "3" + # => "Выхад з функцыі my_function" + +print(my_function.__name__) # => 'my_function' +print(my_function.__code__.co_argcount) # => 2 +``` + +### Бясплатныя анлайн-рэсурсы + +* [Automate the Boring Stuff with Python](https://automatetheboringstuff.com) +* [The Official Docs](https://docs.python.org/3/) +* [Hitchhiker's Guide to Python](https://docs.python-guide.org/en/latest/) +* [Python Course](https://www.python-course.eu) +* [Free Interactive Python Course](http://www.Kikodo.io) +* [First Steps With Python](https://realpython.com/learn/python-first-steps/) +* [A curated list of awesome Python frameworks, libraries and software](https://github.com/vinta/awesome-python) +* [30 Python Language Features and Tricks You May Not Know About](https://sahandsaba.com/thirty-python-language-features-and-tricks-you-may-not-know.html) +* [Official Style Guide for Python](https://www.python.org/dev/peps/pep-0008/) +* [Python 3 Computer Science Circles](https://cscircles.cemc.uwaterloo.ca/) +* [Dive Into Python 3](https://www.diveintopython3.net/index.html) +* [A Crash Course in Python for Scientists](https://nbviewer.jupyter.org/gist/anonymous/5924718) +* [Python Tutorial for Intermediates](https://pythonbasics.org/) +* [Build a Desktop App with Python](https://pythonpyqt.com/)