mirror of
https://github.com/adambard/learnxinyminutes-docs.git
synced 2024-12-23 17:41:41 +00:00
1135 lines
51 KiB
Markdown
1135 lines
51 KiB
Markdown
---
|
||
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://github.com/lucii7vel"]
|
||
filename: learnpython-by.py
|
||
---
|
||
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/)
|