summaryrefslogtreecommitdiffhomepage
path: root/be-by/python-by.html.markdown
diff options
context:
space:
mode:
Diffstat (limited to 'be-by/python-by.html.markdown')
-rw-r--r--be-by/python-by.html.markdown1136
1 files changed, 1136 insertions, 0 deletions
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)) # => <class 'int'>
+type((1,)) # => <class 'tuple'>
+type(()) # => <class 'tuple'>
+
+# Большасць аперацый для спісаў працуюць таксама на картэжах
+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__) # => (<class '__main__.Superhero'>,
+ # => <class 'human.Human'>, <class 'object'>)
+
+ # Вызывае метад папярэдніка, але выкарыстоўвае ўласны атрыбут класа
+ 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__) # => (<class '__main__.Batman'>,
+ # => <class 'superhero.Superhero'>,
+ # => <class 'human.Human'>,
+ # => <class 'bat.Bat'>, <class 'object'>)
+
+ # Вызывае метад папярэдніка, але выкарыстоўвае ўласныя атрыбуты
+ 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/)