Язык Python был создан Гвидо ван Россумом в начале 90-х. Сейчас это один из самых популярных языков. Я влюбился в Python за понятный и доходчивый синтаксис — это почти что исполняемый псевдокод.
1# Однострочные комментарии начинаются с символа решётки.
2
3""" Многострочный текст может быть
4 записан, используя 3 знака " и обычно используется
5 в качестве встроенной документации
6"""
7
8####################################################
9## 1. Примитивные типы данных и операторы
10####################################################
11
12# У вас есть числа
133 # => 3
14
15# Математика работает вполне ожидаемо
161 + 1 # => 2
178 - 1 # => 7
1810 * 2 # => 20
1935 / 5 # => 7.0
20
21# Результат целочисленного деления округляется в меньшую сторону
22# как для положительных, так и для отрицательных чисел.
235 // 3 # => 1
24-5 // 3 # => -2
255.0 // 3.0 # => 1.0 # работает и для чисел с плавающей запятой
26-5.0 // 3.0 # => -2.0
27
28# Результат деления возвращает число с плавающей запятой
2910.0 / 3 # => 3.3333333333333335
30
31# Остаток от деления
327 % 3 # => 1
33
34# Возведение в степень
352**3 # => 8
36
37# Приоритет операций указывается скобками
381 + 3 * 2 # => 7
39(1 + 3) * 2 # => 8
40
41# Булевы значения - примитивы (Обратите внимание на заглавную букву)
42True # => True
43False # => False
44
45# Для отрицания используется ключевое слово not
46not True # => False
47not False # => True
48
49# Булевы операторы
50# Обратите внимание: ключевые слова "and" и "or" чувствительны к регистру букв
51True and False # => False
52False or True # => True
53
54# True и False на самом деле 1 и 0, но с разными ключевыми словами
55True + True # => 2
56True * 8 # => 8
57False - 5 # => -5
58
59# Операторы сравнения обращают внимание на числовое значение True и False
600 == False # => True
611 == True # => True
622 == True # => False
63-5 != False # => True
64
65# Использование булевых логических операторов на типах int превращает их в булевы значения, но возвращаются оригинальные значения
66# Не путайте с bool(ints) и bitwise and/or (&,|)
67bool(0) # => False
68bool(4) # => True
69bool(-6) # => True
700 and 2 # => 0
71-5 or 0 # => -5
72
73# Равенство — это ==
741 == 1 # => True
752 == 1 # => False
76
77# Неравенство — это !=
781 != 1 # => False
792 != 1 # => True
80
81# Ещё немного сравнений
821 < 10 # => True
831 > 10 # => False
842 <= 2 # => True
852 >= 2 # => True
86
87# Проверка, находится ли значение в диапазоне
881 < 2 and 2 < 3 # => True
892 < 3 and 3 < 2 # => False
90
91# Сравнения могут быть записаны цепочкой
921 < 2 < 3 # => True
932 < 3 < 2 # => False
94
95# (is vs. ==) ключевое слово is проверяет, относятся ли две переменные к одному и тому же объекту, но == проверяет если указанные объекты имеют одинаковые значения.
96a = [1, 2, 3, 4] # a указывает на новый список, [1, 2, 3, 4]
97b = a # b указывает на то, что указывает a
98b is a # => True, a и b относятся к одному и тому же объекту
99b == a # => True, Объекты a и b равны
100b = [1, 2, 3, 4] # b указывает на новый список, [1, 2, 3, 4]
101b is a # => False, a и b не относятся к одному и тому же объекту
102b == a # => True, Объекты a и b равны
103
104# Строки определяются символом " или '
105"Это строка."
106'Это тоже строка.'
107
108# И строки тоже могут складываться!
109"Привет " + "мир!" # => "Привет мир!"
110
111# Строки (но не переменные) могут быть объединены без использования '+'
112"Привет " "мир!" # => "Привет мир!"
113
114# Со строкой можно работать, как со списком символов
115"Привет мир!"[0] # => 'П'
116
117# Вы можете найти длину строки
118len("Это строка") # => 10
119
120# Вы также можете форматировать, используя f-строки (в Python 3.6+)
121name = "Рейко"
122f"Она сказала, что ее зовут {name}." # => "Она сказала, что ее зовут Рейко"
123# Вы можете поместить любой оператор Python в фигурные скобки, и он будет выведен в строке.
124f"{name} состоит из {len(name)} символов." # => "Рэйко состоит из 5 символов."
125
126
127# None является объектом
128None # => None
129
130# Не используйте оператор равенства "==" для сравнения
131# объектов с None. Используйте для этого "is"
132"etc" is None # => False
133None is None # => True
134
135# None, 0 и пустые строки/списки/словари/кортежи приводятся к False.
136# Все остальные значения равны True
137bool(0) # => False
138bool("") # => False
139bool([]) # => False
140bool({}) # => False
141bool(()) # => False
142
143
144####################################################
145## 2. Переменные и Коллекции
146####################################################
147
148# В Python есть функция Print
149print("Я Python. Приятно познакомиться!") # => Я Python. Приятно познакомиться!
150
151# По умолчанию, функция print() также выводит новую строку в конце.
152# Используйте необязательный аргумент end, чтобы изменить конец последней строки.
153print("Привет мир", end="!") # => Привет мир!
154
155# Простой способ получить входные данные из консоли
156input_string_var = input("Введите данные: ") # Возвращает данные в виде строки
157# Примечание: в более ранних версиях Python метод input() назывался raw_input()
158
159# Объявлять переменные перед инициализацией не нужно.
160# По соглашению используется нижний_регистр_с_подчёркиваниями
161some_var = 5
162some_var # => 5
163
164# При попытке доступа к неинициализированной переменной выбрасывается исключение.
165# Об исключениях см. раздел "Поток управления и итерируемые объекты".
166some_unknown_var # Выбрасывает ошибку NameError
167
168# if можно использовать как выражение
169# Эквивалент тернарного оператора '?:' в C
170"да!" if 0 > 1 else "нет!" # => "нет!"
171
172# Списки хранят последовательности
173li = []
174# Можно сразу начать с заполненного списка
175other_li = [4, 5, 6]
176
177# Объекты добавляются в конец списка методом append()
178li.append(1) # [1]
179li.append(2) # [1, 2]
180li.append(4) # [1, 2, 4]
181li.append(3) # [1, 2, 4, 3]
182# И удаляются с конца методом pop()
183li.pop() # => возвращает 3 и li становится равен [1, 2, 4]
184# Положим элемент обратно
185li.append(3) # [1, 2, 4, 3].
186
187# Обращайтесь со списком, как с обычным массивом
188li[0] # => 1
189
190# Обратимся к последнему элементу
191li[-1] # => 3
192
193# Попытка выйти за границы массива приведёт к ошибке индекса
194li[4] # Выбрасывает ошибку IndexError
195
196# Можно обращаться к диапазону, используя так называемые срезы
197# (Для тех, кто любит математику, это называется замкнуто-открытый интервал).
198li[1:3] # Вернуть список из индекса с 1 по 3 => [2, 4]
199li[2:] # Вернуть список, начиная с индекса 2 => [4, 3]
200li[:3] # Вернуть список с начала до индекса 3 => [1, 2, 4]
201li[::2] # Вернуть список, выбирая каждую вторую запись => [1, 4]
202li[::-1] # Вернуть список в обратном порядке => [3, 4, 2, 1]
203# Используйте сочетания всего вышеназванного для выделения более сложных срезов
204# li[начало:конец:шаг]
205
206# Сделать однослойную глубокую копию, используя срезы
207li2 = li[:] # => li2 = [1, 2, 4, 3], но (li2 is li) вернет False.
208
209# Удаляем произвольные элементы из списка оператором del
210del li[2] # [1, 2, 3]
211
212# Удалить первое вхождение значения
213li.remove(2) # [1, 3]
214li.remove(2) # Выбрасывает ошибку ValueError поскольку 2 нет в списке
215
216# Вставить элемент по определенному индексу
217li.insert(1, 2) # [1, 2, 3]
218
219# Получить индекс первого найденного элемента, соответствующего аргументу
220li.index(2) # => 1
221li.index(4) # Выбрасывает ошибку ValueError поскольку 4 нет в списке
222
223# Вы можете складывать, или, как ещё говорят, конкатенировать списки
224# Обратите внимание: значения li и other_li при этом не изменились.
225li + other_li # => [1, 2, 3, 4, 5, 6]
226
227# Объединять списки можно методом extend()
228li.extend(other_li) # Теперь li содержит [1, 2, 3, 4, 5, 6]
229
230# Проверить элемент на наличие в списке можно оператором in
2311 in li # => True
232
233# Длина списка вычисляется функцией len
234len(li) # => 6
235
236
237# Кортежи похожи на списки, только неизменяемые
238tup = (1, 2, 3)
239tup[0] # => 1
240tup[0] = 3 # Выбрасывает ошибку TypeError
241
242# Обратите внимание, что кортеж длины 1 должен иметь запятую после последнего элемента, но кортежи другой длины, даже 0, не должны.
243type((1)) # => <class 'int'>
244type((1,)) # => <class 'tuple'>
245type(()) # => <class 'tuple'>
246
247# Всё то же самое можно делать и с кортежами
248len(tup) # => 3
249tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6)
250tup[:2] # => (1, 2)
2512 in tup # => True
252
253# Вы можете распаковывать кортежи (или списки) в переменные
254a, b, c = (1, 2, 3) # a == 1, b == 2 и c == 3
255# Вы также можете сделать расширенную распаковку
256a, *b, c = (1, 2, 3, 4) # a теперь 1, b теперь [2, 3] и c теперь 4
257# Кортежи создаются по умолчанию, если опущены скобки
258d, e, f = 4, 5, 6 # кортеж 4, 5, 6 распаковывается в переменные d, e и f
259# соответственно, d = 4, e = 5 и f = 6
260# Обратите внимание, как легко поменять местами значения двух переменных
261e, d = d, e # теперь d == 5, а e == 4
262
263
264# Словари содержат ассоциативные массивы
265empty_dict = {}
266# Вот так описывается предзаполненный словарь
267filled_dict = {"one": 1, "two": 2, "three": 3}
268
269# Обратите внимание, что ключи для словарей должны быть неизменяемыми типами. Это
270# сделано для того, чтобы ключ мог быть преобразован в хеш для быстрого поиска.
271# Неизменяемые типы включают целые числа, числа с плавающей запятой, строки,
272# кортежи.
273invalid_dict = {[1,2,3]: "123"} # => Выбрасывает ошибку TypeError: unhashable type: 'list'
274valid_dict = {(1,2,3):[1,2,3]} # Однако значения могут быть любого типа.
275
276# Поиск значений с помощью []
277filled_dict["one"] # => 1
278
279# Все ключи в виде списка получаются с помощью метода keys(). Его вызов нужно
280# обернуть в list(), так как обратно мы получаем итерируемый объект, о которых
281# поговорим позднее. Примечание - для Python версии <3.7, порядок словарных
282# ключей не гарантируется. Ваши результаты могут не точно соответствовать
283# приведенному ниже примеру. Однако, начиная с Python 3.7 элементы в словаре
284# сохраняют порядок, в котором они вставляются в словарь.
285list(filled_dict.keys()) # => ["three", "two", "one"] в Python <3.7
286list(filled_dict.keys()) # => ["one", "two", "three"] в Python 3.7+
287
288
289# Все значения в виде списка можно получить с помощью values().
290# И снова нам нужно обернуть вызов в list(), чтобы превратить
291# итерируемый объект в список.
292# То же самое замечание насчёт порядка ключей справедливо и здесь
293list(filled_dict.values()) # => [3, 2, 1] в Python <3.7
294list(filled_dict.values()) # => [1, 2, 3] в Python 3.7+
295
296# При помощи ключевого слова in можно проверять наличие ключей в словаре
297"one" in filled_dict # => True
2981 in filled_dict # => False
299
300# Попытка получить значение по несуществующему ключу выбросит ошибку KeyError
301filled_dict["four"] # Выбрасывает ошибку KeyError
302
303# Чтобы избежать этого, используйте метод get()
304filled_dict.get("one") # => 1
305filled_dict.get("four") # => None
306# Метод get поддерживает аргумент по умолчанию, когда значение отсутствует
307filled_dict.get("one", 4) # => 1
308filled_dict.get("four", 4) # => 4
309
310# Метод setdefault() вставляет пару ключ-значение, только если такого ключа нет
311filled_dict.setdefault("five", 5) # filled_dict["five"] возвращает 5
312filled_dict.setdefault("five", 6) # filled_dict["five"] по-прежнему возвращает 5
313
314# Добавление элементов в словарь
315filled_dict.update({"four":4}) # => {"one": 1, "two": 2, "three": 3, "four": 4}
316filled_dict["four"] = 4 # Другой способ добавления элементов
317
318# Удаляйте ключи из словаря с помощью ключевого слова del
319del filled_dict["one"] # Удаляет ключ "one" из словаря
320
321# В Python 3.5+ вы также можете использовать дополнительные параметры распаковки
322{'a': 1, **{'b': 2}} # => {'a': 1, 'b': 2}
323{'a': 1, **{'a': 2}} # => {'a': 2}
324
325
326# Множества содержат... ну, в общем, множества
327empty_set = set()
328# Инициализация множества набором значений.
329# Да, оно выглядит примерно как словарь. Ну извините, так уж вышло.
330filled_set = {1, 2, 2, 3, 4} # => {1, 2, 3, 4}
331
332# Как и ключи словаря, элементы множества должны быть неизменяемыми.
333invalid_set = {[1], 1} # => Выбрасывает ошибку TypeError: unhashable type: 'list'
334valid_set = {(1,), 1}
335
336# Множеству можно назначать новую переменную
337filled_set = some_set
338filled_set.add(5) # {1, 2, 3, 4, 5}
339# В множествах нет повторяющихся элементов
340filled_set.add(5) # {1, 2, 3, 4, 5}
341
342# Пересечение множеств: &
343other_set = {3, 4, 5, 6}
344filled_set & other_set # => {3, 4, 5}
345
346# Объединение множеств: |
347filled_set | other_set # => {1, 2, 3, 4, 5, 6}
348
349# Разность множеств: -
350{1, 2, 3, 4} - {2, 3, 5} # => {1, 4}
351
352# Симметричная разница: ^
353{1, 2, 3, 4} ^ {2, 3, 5} # => {1, 4, 5}
354
355# Проверить, является ли множество слева надмножеством множества справа
356{1, 2} >= {1, 2, 3} # => False
357
358# Проверить, является ли множество слева подмножеством множества справа
359{1, 2} <= {1, 2, 3} # => True
360
361# Проверка на наличие в множестве: in
3622 in filled_set # => True
36310 in filled_set # => False
364
365# Сделать однослойную глубокую копию
366filled_set = some_set.copy() # {1, 2, 3, 4, 5}
367filled_set is some_set # => False
368
369
370####################################################
371## 3. Поток управления и итерируемые объекты
372####################################################
373
374# Для начала создадим переменную
375some_var = 5
376
377# Так выглядит выражение if. Отступы в python очень важны!
378# Конвенция заключается в использовании четырех пробелов, а не табуляции.
379# Pезультат: "some_var меньше, чем 10"
380if some_var > 10:
381 print("some_var точно больше, чем 10.")
382elif some_var < 10: # Выражение elif необязательно.
383 print("some_var меньше, чем 10.")
384else: # Это тоже необязательно.
385 print("some_var равно 10.")
386
387
388"""
389Циклы For проходят по спискам.
390Выводит:
391 собака — это млекопитающее
392 кошка — это млекопитающее
393 мышь — это млекопитающее
394"""
395for animal in ["собака", "кошка", "мышь"]:
396 # Можете использовать format() для интерполяции форматированных строк
397 print("{} — это млекопитающее".format(animal))
398
399"""
400"range(число)" возвращает список чисел от нуля до заданного числа.
401Выводит:
402 0
403 1
404 2
405 3
406"""
407for i in range(4):
408 print(i)
409
410"""
411"range(начало, конец)" возвращает список чисел от начального числа
412к конечному, не включая конечное.
413Выводит:
414 4
415 5
416 6
417 7
418"""
419for i in range(4, 8):
420 print(i)
421
422"""
423"range(начало, конец, шаг)" возвращает список чисел от начального
424числа к конечному, увеличивая шаг за шагом.
425Если шаг не указан, значение по умолчанию - 1.
426Выводит:
427 4
428 6
429"""
430for i in range(4, 8, 2):
431 print(i)
432
433"""
434Можно перебрать список и получить индекс и значение каждого элемента в списке
435Выводит:
436 0 собака
437 1 кошка
438 2 мышь
439"""
440animals = ["собака", "кошка", "мышь"]
441for i, value in enumerate(animals):
442 print(i, value)
443
444"""
445Циклы while продолжаются до тех пор, пока указанное условие не станет ложным.
446Выводит:
447 0
448 1
449 2
450 3
451"""
452x = 0
453while x < 4:
454 print(x)
455 x += 1 # Краткая запись для x = x + 1
456
457
458# Обрабатывайте исключения блоками try/except
459try:
460 # Чтобы выбросить ошибку, используется raise
461 raise IndexError("Это ошибка индекса")
462except IndexError as e:
463 pass # pass — это просто отсутствие оператора. Обычно здесь происходит восстановление после ошибки.
464except (TypeError, NameError):
465 pass # Можно обработать больше одного исключения.
466else: # Необязательно. Добавляется за последним except.
467 print("Всё хорошо!") # Выполнится, только если не было никаких исключений.
468finally: # Необязательно. Выполнить при любых обстоятельствах.
469 print("Мы можем очистить ресурсы здесь")
470
471# Вместо try/finally чтобы очистить ресурсы, можно использовать оператор with
472with open("myfile.txt") as f:
473 for line in f:
474 print(line)
475
476# Запись в файл
477contents = {"aa": 12, "bb": 21}
478with open("myfile1.txt", "w+") as file:
479 file.write(str(contents)) # Записывает строку в файл
480
481with open("myfile2.txt", "w+") as file:
482 file.write(json.dumps(contents)) # Записывает объект в файл
483
484# Чтение из файла
485with open("myfile1.txt", "r+") as file:
486 contents = file.read() # Читает строку из файла
487print(contents) # => '{"aa": 12, "bb": 21}'
488
489with open("myfile2.txt", "r") as file:
490 contents = json.load(file) # Читает объект json из файла
491print(contents) # => {"aa": 12, "bb": 21}
492
493
494# Python предоставляет фундаментальную абстракцию,
495# которая называется итерируемым объектом (Iterable).
496# Итерируемый объект — это объект, который воспринимается как последовательность.
497# Объект, который возвратила функция range() — итерируемый.
498
499filled_dict = {"one": 1, "two": 2, "three": 3}
500our_iterable = filled_dict.keys()
501print(our_iterable) # => dict_keys(['one', 'two', 'three']). Это объект, реализующий интерфейс Iterable
502
503# Мы можем проходить по нему циклом.
504for i in our_iterable:
505 print(i) # Выводит one, two, three
506
507# Но мы не можем обращаться к элементу по индексу.
508our_iterable[1] # Выбрасывает ошибку TypeError
509
510# Итерируемый объект знает, как создавать итератор.
511our_iterator = iter(our_iterable)
512
513# Итератор может запоминать состояние при проходе по объекту.
514# Мы получаем следующий объект, вызывая функцию next().
515next(our_iterator) # => "one"
516
517# Он сохраняет состояние при вызове next().
518next(our_iterator) # => "two"
519next(our_iterator) # => "three"
520
521# Возвратив все данные, итератор выбрасывает исключение StopIteration
522next(our_iterator) # Выбрасывает исключение StopIteration
523
524# Мы можем проходить по нему циклом.
525our_iterator = iter(our_iterable)
526for i in our_iterator:
527 print(i) # Выводит one, two, three
528
529# Вы можете получить сразу все элементы итератора, вызвав на нём функцию list().
530list(our_iterable) # => Возвращает ["one", "two", "three"]
531list(our_iterator) # => Возвращает [] потому что состояние сохраняется
532
533
534####################################################
535## 4. Функции
536####################################################
537
538# Используйте def для создания новых функций
539def add(x, y):
540 print("x равен %s, а y равен %s" % (x, y))
541 return x + y # Возвращайте результат с помощью ключевого слова return
542
543# Вызов функции с аргументами
544add(5, 6) # => Выводит "x равен 5, а y равен 6" и возвращает 11
545
546# Другой способ вызова функции — вызов с именованными аргументами
547add(y=6, x=5) # Именованные аргументы можно указывать в любом порядке.
548
549# Вы можете определить функцию, принимающую переменное число аргументов
550def varargs(*args):
551 return args
552
553varargs(1, 2, 3) # => (1,2,3)
554
555
556# А также можете определить функцию, принимающую переменное число
557# именованных аргументов
558def keyword_args(**kwargs):
559 return kwargs
560
561# Вызовем эту функцию и посмотрим, что из этого получится
562keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"}
563
564# Если хотите, можете использовать оба способа одновременно
565def all_the_args(*args, **kwargs):
566 print(args)
567 print(kwargs)
568"""
569all_the_args(1, 2, a=3, b=4) выводит:
570 (1, 2)
571 {"a": 3, "b": 4}
572"""
573
574# Вызывая функции, можете сделать наоборот!
575# Используйте символ * для распаковки кортежей и ** для распаковки словарей
576args = (1, 2, 3, 4)
577kwargs = {"a": 3, "b": 4}
578all_the_args(*args) # эквивалентно all_the_args(1, 2, 3, 4)
579all_the_args(**kwargs) # эквивалентно all_the_args(a=3, b=4)
580all_the_args(*args, **kwargs) # эквивалентно all_the_args(1, 2, 3, 4, a=3, b=4)
581
582# Возврат нескольких значений (с назначением кортежей)
583def swap(x, y):
584 return y, x # Возвращает несколько значений в виде кортежа без скобок.
585 # (Примечание: скобки исключены, но могут быть включены)
586
587x = 1
588y = 2
589x, y = swap(x, y) # => x = 2, y = 1
590# (x, y) = swap(x,y) # Снова, скобки были исключены, но могут быть включены.
591
592# Область определения функций
593x = 5
594
595def set_x(num):
596 # Локальная переменная x — это не то же самое, что глобальная переменная x
597 x = num # => 43
598 print(x) # => 43
599
600def set_global_x(num):
601 global x
602 print(x) # => 5
603 x = num # Глобальная переменная x теперь равна 6
604 print(x) # => 6
605
606set_x(43)
607set_global_x(6)
608
609# Python имеет функции первого класса
610def create_adder(x):
611 def adder(y):
612 return x + y
613 return adder
614
615add_10 = create_adder(10)
616add_10(3) # => 13
617
618# Также есть и анонимные функции
619(lambda x: x > 2)(3) # => True
620(lambda x, y: x ** 2 + y ** 2)(2, 1) # => 5
621
622# Есть встроенные функции высшего порядка
623list(map(add_10, [1, 2, 3])) # => [11, 12, 13]
624list(map(max, [1, 2, 3], [4, 2, 1])) # => [4, 2, 3]
625
626list(filter(lambda x: x > 5, [3, 4, 5, 6, 7])) # => [6, 7]
627
628# Для удобного отображения и фильтрации можно использовать списочные интерпретации
629# Интерпретация списка сохраняет вывод в виде списка, который сам может быть вложенным списком
630[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13]
631[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7]
632
633# Вы также можете создавать интерпретации множеств и словарей.
634{x for x in 'abcddeef' if x not in 'abc'} # => {'d', 'e', 'f'}
635{x: x**2 for x in range(5)} # => {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
636
637
638####################################################
639## 5. Модули
640####################################################
641
642# Вы можете импортировать модули
643import math
644print(math.sqrt(16)) # => 4.0
645
646# Вы можете получить определенные функции из модуля
647from math import ceil, floor
648print(ceil(3.7)) # => 4.0
649print(floor(3.7)) # => 3.0
650
651# Вы можете импортировать все функции из модуля.
652# Предупреждение: это не рекомендуется
653from math import *
654
655# Вы можете сократить имена модулей
656import math as m
657math.sqrt(16) == m.sqrt(16) # => True
658
659# Модули Python - это обычные файлы Python. Вы
660# можете писать свои собственные и импортировать их. Имя
661# модуля совпадает с именем файла.
662
663# Вы можете узнать, какие функции и атрибуты
664# определены в модуле.
665import math
666dir(math)
667
668# Если у вас есть скрипт Python с именем math.py в той же папке,
669# что и ваш текущий скрипт, файл math.py будет
670# будет загружен вместо встроенного модуля Python.
671# Это происходит потому, что локальная папка имеет приоритет
672# над встроенными библиотеками Python.
673
674
675####################################################
676## 6. Классы
677####################################################
678
679# Мы используем оператор class для создания класса
680class Human:
681
682 # Атрибут класса. Он используется всеми экземплярами этого класса
683 species = "Гомосапиенс"
684
685 # Обычный конструктор, вызывается при инициализации экземпляра класса
686 # Обратите внимание, что двойное подчёркивание в начале и в конце имени
687 # означает объекты и атрибуты, которые используются Python, но находятся
688 # в пространствах имён, управляемых пользователем.
689 # Методы (или объекты или атрибуты), например:
690 # __init__, __str__, __repr__ и т. д. называются специальными методами.
691 # Не придумывайте им имена самостоятельно.
692 def __init__(self, name):
693 # Присваивание значения аргумента атрибуту
694 self.name = name
695
696 # Инициализация свойства
697 self._age = 0
698
699 # Метод экземпляра. Все методы принимают self в качестве первого аргумента
700 def say(self, msg):
701 return "{name}: {message}".format(name=self.name, message=msg)
702
703 # Другой метод экземпляра
704 def sing(self):
705 return 'йо... йо... проверка микрофона... раз, два... раз, два...'
706
707 # Метод класса разделяется между всеми экземплярами
708 # Они вызываются с указыванием вызывающего класса в качестве первого аргумента
709 @classmethod
710 def get_species(cls):
711 return cls.species
712
713 # Статический метод вызывается без ссылки на класс или экземпляр
714 @staticmethod
715 def grunt():
716 return "*grunt*"
717
718 # property похоже на геттер.
719 # Оно превращает метод age() в одноименный атрибут только для чтения.
720 # Однако нет необходимости писать тривиальные геттеры и сеттеры в Python.
721 @property
722 def age(self):
723 return self._age
724
725 # Это позволяет установить свойство
726 @age.setter
727 def age(self, age):
728 self._age = age
729
730 # Это позволяет удалить свойство
731 @age.deleter
732 def age(self):
733 del self._age
734
735
736# Когда интерпретатор Python читает исходный файл, он выполняет весь его код.
737# Проверка __name__ гарантирует, что этот блок кода выполняется только тогда, когда
738# этот модуль - это основная программа.
739if __name__ == '__main__':
740 # Инициализация экземпляра класса
741 i = Human(name="Иван")
742 i.say("привет") # Выводит: "Иван: привет"
743 j = Human("Пётр")
744 j.say("привет") # Выводит: "Пётр: привет"
745 # i и j являются экземплярами типа Human, или другими словами: они являются объектами Human
746
747 # Вызов метода класса
748 i.say(i.get_species()) # "Иван: Гомосапиенс"
749 # Изменение разделяемого атрибута
750 Human.species = "Неандертальец"
751 i.say(i.get_species()) # => "Иван: Неандертальец"
752 j.say(j.get_species()) # => "Пётр: Неандертальец"
753
754 # Вызов статического метода
755 print(Human.grunt()) # => "*grunt*"
756
757 # Невозможно вызвать статический метод с экземпляром объекта
758 # потому что i.grunt() автоматически поместит "self" (объект i) в качестве аргумента
759 print(i.grunt()) # => TypeError: grunt() takes 0 positional arguments but 1 was given
760
761 # Обновить свойство для этого экземпляра
762 i.age = 42
763 # Получить свойство
764 i.say(i.age) # => "Иван: 42"
765 j.say(j.age) # => "Пётр: 0"
766 # Удалить свойство
767 del i.age
768 # i.age # => это выбрасило бы ошибку AttributeError
769
770
771####################################################
772## 6.1 Наследование
773####################################################
774
775# Наследование позволяет определять новые дочерние классы, которые наследуют методы и
776# переменные от своего родительского класса.
777
778# Используя класс Human, определенный выше как базовый или родительский класс, мы можем
779# определить дочерний класс Superhero, который наследует переменные класса, такие как
780# "species", "name" и "age", а также методы, такие как "sing" и "grunt" из класса Human,
781# но также может иметь свои уникальные свойства.
782
783# Чтобы воспользоваться преимуществами модульности по файлам, вы можете поместить
784# вышеперечисленные классы в их собственные файлы, например, human.py
785
786# Чтобы импортировать функции из других файлов, используйте следующий формат
787# from "имя-файла-без-расширения" import "функция-или-класс"
788
789from human import Human
790
791
792# Укажите родительский класс(ы) как параметры определения класса
793class Superhero(Human):
794
795 # Если дочерний класс должен наследовать все определения родителя без каких-либо
796 # изменений, вы можете просто использовать ключевое слово pass (и ничего больше),
797 # но в этом случае оно закомментировано, чтобы разрешить уникальный дочерний класс:
798 # pass
799
800 # Дочерние классы могут переопределять атрибуты своих родителей
801 species = 'Сверхчеловек'
802
803 # Дочерние классы автоматически наследуют конструктор родительского класса, включая
804 # его аргументы, но также могут определять дополнительные аргументы или определения
805 # и переопределять его методы, такие как конструктор класса.
806 # Этот конструктор наследует аргумент "name" от класса "Human"
807 # и добавляет аргументы "superpower" и "movie":
808 def __init__(self, name, movie=False,
809 superpowers=["сверхсила", "пуленепробиваемость"]):
810
811 # добавить дополнительные атрибуты класса:
812 self.fictional = True
813 self.movie = movie
814 # помните об изменяемых значениях по умолчанию,
815 # поскольку значения по умолчанию являются общими
816 self.superpowers = superpowers
817
818 # Функция "super" позволяет вам получить доступ к методам родительского класса,
819 # которые переопределяются дочерним, в данном случае, методом __init__.
820 # Это вызывает конструктор родительского класса:
821 super().__init__(name)
822
823 # переопределить метод sing
824 def sing(self):
825 return 'Бам, бам, БАМ!'
826
827 # добавить дополнительный метод экземпляра
828 def boast(self):
829 for power in self.superpowers:
830 print("Я обладаю силой '{pow}'!".format(pow=power))
831
832
833if __name__ == '__main__':
834 sup = Superhero(name="Тик")
835
836 # Проверка типа экземпляра
837 if isinstance(sup, Human):
838 print('Я человек')
839 if type(sup) is Superhero:
840 print('Я супергерой')
841
842 # Получить порядок поиска разрешения метода (MRO),
843 # используемый как getattr(), так и super()
844 # Этот атрибут является динамическим и может быть обновлен
845 print(Superhero.__mro__) # => (<class '__main__.Superhero'>,
846 # => <class 'human.Human'>, <class 'object'>)
847
848 # Вызывает родительский метод, но использует свой собственный атрибут класса
849 print(sup.get_species()) # => Сверхчеловек
850
851 # Вызов переопределенного метода
852 print(sup.sing()) # => Бам, бам, БАМ!
853
854 # Вызывает метод из Human
855 sup.say('Ложка') # => Тик: Ложка
856
857 # Метод вызова, существующий только в Superhero
858 sup.boast() # => Я обладаю силой 'сверхсила'!
859 # => Я обладаю силой 'пуленепробиваемость'!
860
861 # Атрибут унаследованного класса
862 sup.age = 31
863 print(sup.age) # => 31
864
865 # Атрибут, который существует только в Superhero
866 print('Достоин ли я Оскара? ' + str(sup.movie))
867
868
869####################################################
870## 6.2 Множественное наследование
871####################################################
872
873# Eще одно определение класса
874# bat.py
875class Bat:
876
877 species = 'Летучая мышь'
878
879 def __init__(self, can_fly=True):
880 self.fly = can_fly
881
882 # В этом классе также есть метод say
883 def say(self, msg):
884 msg = '... ... ...'
885 return msg
886
887 # И свой метод тоже
888 def sonar(self):
889 return '))) ... ((('
890
891if __name__ == '__main__':
892 b = Bat()
893 print(b.say('привет'))
894 print(b.fly)
895
896
897# И еще одно определение класса, унаследованное от Superhero и Bat
898# superhero.py
899from superhero import Superhero
900from bat import Bat
901
902# Определите Batman как дочерний класс, унаследованный от Superhero и Bat
903class Batman(Superhero, Bat):
904
905 def __init__(self, *args, **kwargs):
906 # Обычно для наследования атрибутов необходимо вызывать super:
907 # super(Batman, self).__init__(*args, **kwargs)
908 # Однако здесь мы имеем дело с множественным наследованием, а super()
909 # работает только со следующим базовым классом в списке MRO.
910 # Поэтому вместо этого мы вызываем __init__ для всех родителей.
911 # Использование *args и **kwargs обеспечивает чистый способ передачи
912 # аргументов, когда каждый родитель "очищает слой луковицы".
913 Superhero.__init__(self, 'анонимный', movie=True,
914 superpowers=['Богатый'], *args, **kwargs)
915 Bat.__init__(self, *args, can_fly=False, **kwargs)
916 # переопределить значение атрибута name
917 self.name = 'Грустный Бен Аффлек'
918
919 def sing(self):
920 return 'на на на на на бэтмен!'
921
922
923if __name__ == '__main__':
924 sup = Batman()
925
926 # Получить порядок поиска разрешения метода (MRO),
927 # используемый как getattr(), так и super()
928 # Этот атрибут является динамическим и может быть обновлен
929 print(Batman.__mro__) # => (<class '__main__.Batman'>,
930 # => <class 'superhero.Superhero'>,
931 # => <class 'human.Human'>,
932 # => <class 'bat.Bat'>, <class 'object'>)
933
934 # Вызывает родительский метод, но использует свой собственный атрибут класса
935 print(sup.get_species()) # => Сверхчеловек
936
937 # Вызов переопределенного метода
938 print(sup.sing()) # => на на на на на бэтмен!
939
940 # Вызывает метод из Human, потому что порядок наследования имеет значение
941 sup.say('Я согласен') # => Грустный Бен Аффлек: Я согласен
942
943 # Вызов метода, существующий только во втором родителе
944 print(sup.sonar()) # => ))) ... (((
945
946 # Атрибут унаследованного класса
947 sup.age = 100
948 print(sup.age) # => 100
949
950 # Унаследованный атрибут от второго родителя,
951 # значение по умолчанию которого было переопределено.
952 print('Могу ли я летать? ' + str(sup.fly)) # => Могу ли я летать? False
953
954
955####################################################
956## 7. Дополнительно
957####################################################
958
959# Генераторы помогут выполнить ленивые вычисления
960def double_numbers(iterable):
961 for i in iterable:
962 yield i + i
963
964# Генераторы эффективны с точки зрения памяти, потому что они загружают только данные,
965# необходимые для обработки следующего значения в итерации.
966# Это позволяет им выполнять операции с недопустимо большими диапазонами значений.
967# ПРИМЕЧАНИЕ: "range" заменяет "xrange" в Python 3.
968for i in double_numbers(range(1, 900000000)): # "range" - генератор.
969 print(i)
970 if i >= 30:
971 break
972
973# Так же, как вы можете создать интерпретации списков, вы можете создать и
974# интерпретации генераторов.
975values = (-x for x in [1,2,3,4,5])
976for x in values:
977 print(x) # Выводит -1 -2 -3 -4 -5
978
979# Вы также можете преобразовать интерпретацию генератора непосредственно в список.
980values = (-x for x in [1,2,3,4,5])
981gen_to_list = list(values)
982print(gen_to_list) # => [-1, -2, -3, -4, -5]
983
984
985# Декораторы
986# В этом примере "beg" оборачивает "say".
987# Если say_please равно True, он изменит возвращаемое сообщение.
988from functools import wraps
989
990
991def beg(target_function):
992 @wraps(target_function)
993 def wrapper(*args, **kwargs):
994 msg, say_please = target_function(*args, **kwargs)
995 if say_please:
996 return "{} {}".format(msg, "Пожалуйста! У меня нет денег :(")
997 return msg
998
999 return wrapper
1000
1001
1002@beg
1003def say(say_please=False):
1004 msg = "Вы не купите мне пива?"
1005 return msg, say_please
1006
1007
1008print(say()) # Вы не купите мне пива?
1009print(say(say_please=True)) # Вы не купите мне пива? Пожалуйста! У меня нет денег :(
Хотите ещё? ¶
Бесплатные онлайн-материалы ¶
- Automate the Boring Stuff with Python
- Официальная документация
- Hitchhiker’s Guide to Python
- Python Course
- First Steps With Python
- A curated list of awesome Python frameworks, libraries and software
- Official Style Guide for Python
- Python 3 Computer Science Circles
- Dive Into Python 3
- Python Tutorial for Intermediates
- Build a Desktop App with Python