learnxinyminutes-docs/be/python.md
2024-12-08 20:29:09 -07:00

1136 lines
51 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
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
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/)