Примеры кода на python: Примеры кода шпаргалок в Python
Примеры кода шпаргалок в Python
Многие люди начинают переезжать с версии 2 на 3 из-за Python EOL (Поддержка Python 2.7 прекратиться с 2020 года). К сожалению, часто Python 3 выглядит как Python 2 со скобками. В статье я покажу несколько примеров существующих функций, которыми вы можете пользоваться только в Python 3, с надеждой на то, что это поможет решать ваши текущие и будущие задачи.
Есть вопросы по Python?
На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!
Telegram Чат & Канал
Вступите в наш дружный чат по Python и начните общение с единомышленниками! Станьте частью большого сообщества!
Паблик VK
Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!
Все примеры написаны в Python 3.7 и каждая функция содержит минимальную версию Python для этой функции.
F-строки (Python 3.6+)
Сложно делать что-либо без строк в Python и чтобы сохранить адекватность, вам нужно иметь структурированный способ работы со строками. Большая часть людей, работающих с Python, предпочитают метод format python.
user = «Андрей»
action = «покупка»
log_message = ‘Пользователь {} зашел на сайт и выполнил действие: {}’.format(
user,
action
)
print(log_message)
# Пользователь Андрей зашел на сайт и выполнил действие: покупка
| user = «Андрей» action = «покупка»
log_message = ‘Пользователь {} зашел на сайт и выполнил действие: {}’.format( user, action )
print(log_message) # Пользователь Андрей зашел на сайт и выполнил действие: покупка |
Наряду с format
, Python 3 предоставляет гибкий способ выполнения интерполяции строк через f-строки. Тот же код, что и показанный выше, с использованием f-strings выглядит так:
user = «Юрий»
action = «продажа»
log_message = f’Пользователь {user} зашел на сайт и выполнил действие: {action}’
print(log_message)
# Пользователь Юрий зашел на сайт и выполнил действие: продажа
| user = «Юрий» action = «продажа»
log_message = f’Пользователь {user} зашел на сайт и выполнил действие: {action}’
print(log_message) # Пользователь Юрий зашел на сайт и выполнил действие: продажа |
Pathlib (Python 3.4+)
F-строки — это отличное решение, но некоторые строки, такие как пути файлов, имеют свои собственные библиотеки, которые заметно упрощают работу. Python 3 предоставляет pathlib в качестве удобной абстракции для работы с путями файлов.
from pathlib import Path
root = Path(‘post_sub_folder’)
print(root)
# post_sub_folder
path = root / ‘happy_user’
# Делаем путь абсолютным
print(path.resolve())
# /home/weenkus/post_sub_folder/happy_user
| from pathlib import Path
root = Path(‘post_sub_folder’) print(root) # post_sub_folder
path = root / ‘happy_user’ # Делаем путь абсолютным
print(path.resolve()) # /home/weenkus/post_sub_folder/happy_user |
Подсказки типов | Ожидание типа | Type hinting (Python 3.5+)
Спор о том, какое типизирование python лучше — статическое или динамическое — не умолкают и по сей день и у каждого есть свое мнение на этот счет. Это личное дело читателя — когда ему нужно вписывать типы, но мне кажется что вы как минимум должны знать о том, что Python 3 поддерживает подсказки типов.
def sentence_has_animal(sentence: str) -> bool:
return «animal» in sentence
print(sentence_has_animal(«У Ивана есть своя собственная Bitcoin ферма»)) # True
| def sentence_has_animal(sentence: str) -> bool: return «animal» in sentence
print(sentence_has_animal(«У Ивана есть своя собственная Bitcoin ферма»)) # True |
Перечисления enum (Python 3.4+)
Python 3 поддерживает простой способ написания перечислений через класс Enum. Этот класс можно назвать удобным способом инкапсуляции списка констант, чтобы они не были разбросаны по всему коду без структуры.
from enum import Enum, auto
class Monster(Enum):
ZOMBIE = auto()
WARRIOR = auto()
BEAR = auto()
print(Monster.ZOMBIE) # Monster.ZOMBIE
| from enum import Enum, auto
class Monster(Enum): ZOMBIE = auto() WARRIOR = auto() BEAR = auto()
print(Monster.ZOMBIE) # Monster.ZOMBIE |
Перечисление — это набор символических имен (членов), связанных уникальным, постоянным значением. С перечислением, члены можно сравнить по идентичности, а само перечисление может повторяться.
for monster in Monster:
print(monster)
# Monster.ZOMBIE
# Monster.WARRIOR
# Monster.BEAR
| for monster in Monster: print(monster)
# Monster.ZOMBIE # Monster.WARRIOR # Monster.BEAR |
Встроенный LRU кэш (Python 3.2+)
Кэш содержится практически в любом горизонтальном отрезке программного обеспечения, которым мы пользуемся сегодня. Python 3 делает их использование очень простым, предоставляя кэш LRU (Least Recently Used) в качестве декоратора под названием lru_cache
.
Внизу показана простая функция Фибоначчи, которая, как мы знаем, выиграет от кэширования, так как выполняет одну и ту же работу несколько раз через рекурсию.
import time
def fib(number: int) -> int:
if number == 0: return 0
if number == 1: return 1
return fib(number-1) + fib(number-2)
start = time.time()
fib(40)
print(f’Duration: {time.time() — start}s’)
# Длительность: 30.684099674224854s
| import time
def fib(number: int) -> int: if number == 0: return 0 if number == 1: return 1
return fib(number-1) + fib(number-2)
start = time.time() fib(40)
print(f’Duration: {time.time() — start}s’) # Длительность: 30.684099674224854s |
Теперь мы можем использовать lru_cache
для оптимизации (эта техника оптимизации называется меморизация). Время выполнения варьирует от секунд до наносекунд.
from functools import lru_cache
@lru_cache(maxsize=512)
def fib_memoization(number: int) -> int:
if number == 0: return 0
if number == 1: return 1
return fib_memoization(number-1) + fib_memoization(number-2)
start = time.time()
fib_memoization(40)
print(f’Duration: {time.time() — start}s’)
# Длительность: 6.866455078125e-05s
| from functools import lru_cache
@lru_cache(maxsize=512) def fib_memoization(number: int) -> int: if number == 0: return 0 if number == 1: return 1
return fib_memoization(number-1) + fib_memoization(number-2)
start = time.time() fib_memoization(40)
print(f’Duration: {time.time() — start}s’) # Длительность: 6.866455078125e-05s |
Повторяемая расширенная распаковка (Python 3.0+)
Здесь код будет говорить сам за себя (документация):
head, *body, tail = range(5)
print(head, body, tail)
# 0 [1, 2, 3] 4
py, filename, *cmds = «python3.7 script.py -n 5 -l 15».split()
print(py)
print(filename)
print(cmds)
# python3.7
# script.py
# [‘-n’, ‘5’, ‘-l’, ’15’]
first, _, third, *_ = range(10)
print(first, third)
# 0 2
| head, *body, tail = range(5) print(head, body, tail) # 0 [1, 2, 3] 4
py, filename, *cmds = «python3.7 script.py -n 5 -l 15».split() print(py) print(filename) print(cmds) # python3.7 # script.py # [‘-n’, ‘5’, ‘-l’, ’15’]
first, _, third, *_ = range(10) print(first, third) # 0 2 |
Классы данных (Python 3.7+)
Python 3 представляет классы данных, которые не имеют большого количества ограничений и могут быть использованы для сокращения стандартного кода, так как декоратор автоматически генерирует специальные методы, такие как __init__()
и __repr()__
. Из официального заявления, они описываются как “изменяемые названные кортежи со значениями по умолчанию”.
class Armor:
def __init__(self, armor: float, description: str, level: int = 1):
self.armor = armor
self.level = level
self.description = description
def power(self) -> float:
return self.armor * self.level
armor = Armor(5.2, «Common armor.», 2)
armor.power()
# 10.4
print(armor)
# <__main__.Armor object at 0x7fc4800e2cf8>
| class Armor:
def __init__(self, armor: float, description: str, level: int = 1): self.armor = armor self.level = level self.description = description
def power(self) -> float: return self.armor * self.level
armor = Armor(5.2, «Common armor.», 2) armor.power() # 10.4
print(armor) # <__main__.Armor object at 0x7fc4800e2cf8> |
Та же реализация класса Armor
при помощи классов данных.
from dataclasses import dataclass
@dataclass
class Armor:
armor: float
description: str
level: int = 1
def power(self) -> float:
return self.armor * self.level
armor = Armor(5.2, «Common armor.», 2)
armor.power()
# 10.4
print(armor)
# Armor(armor=5.2, description=’Common armor.’, level=2)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| from dataclasses import dataclass
@dataclass class Armor: armor: float description: str level: int = 1
def power(self) -> float: return self.armor * self.level
armor = Armor(5.2, «Common armor.», 2) armor.power() # 10.4
print(armor) # Armor(armor=5.2, description=’Common armor.’, level=2) |
Пространства имен (Python 3.3+)
Один из способов структуризации кода Python заключается в пакетах (папки с файлом __init__.py
). Пример ниже предоставлен официальной документацией Python.
sound/ Пакет верхнего уровня
__init__.py Инициализировать звукового пакета
formats/ Подпакет для преобразования формата файла
__init__.py
wavread.py
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
…
effects/ Подпакет для звуковых эффектов
__init__.py
echo.py
surround.py
reverse.py
…
filters/ Подпакет для фильтров
__init__.py
equalizer.py
vocoder.py
karaoke.py
…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| sound/ Пакет верхнего уровня __init__.py Инициализировать звукового пакета formats/ Подпакет для преобразования формата файла __init__.py wavread.py wavwrite.py aiffread.py aiffwrite.py auread.py auwrite.py … effects/ Подпакет для звуковых эффектов __init__.py echo.py surround.py reverse.py … filters/ Подпакет для фильтров __init__.py equalizer.py vocoder.py karaoke.py … |
В Python 2, каждая папка выше должна иметь файл __init__.py
, который делает папку пакетом Python. В Python 3, с появлением неявных пакетов пространств имен, эти файлы больше не нужны.
sound/ Пакет верхнего уровня
__init__.py Инициализировать звукового пакета
formats/ Подпакет для преобразования формата файла
wavread.py
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
…
effects/ Подпакет для звуковых эффектов
echo.py
surround.py
reverse.py
…
filters/ Подпакет для фильтров
equalizer.py
vocoder.py
karaoke.py
…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| sound/ Пакет верхнего уровня __init__.py Инициализировать звукового пакета formats/ Подпакет для преобразования формата файла wavread.py wavwrite.py aiffread.py aiffwrite.py auread.py auwrite.py … effects/ Подпакет для звуковых эффектов echo.py surround.py reverse.py … filters/ Подпакет для фильтров equalizer.py vocoder.py karaoke.py … |
Впрочем, как многие пользователи заметили, это может быть не так просто, как я указал в этом разделе. Согласно спецификации 420 в PEP — файл __init__.py
все еще может понадобиться для обычных пакетов, удаление его из структуры папки превратит его в пакет пространства имен, который включает в себя дополнительные ограничения, официальная документация нативных пакетов пространств имен показывают хорошие примеры тому, а также в них озвучиваются названия всех ограничений.
Подведем итоги
Как и практически любой другой список в интернете, этот нельзя назвать завершенным. Надеюсь в этой статье вы нашли хотя бы одну функцию Python 3, которой вы ранее не пользовались, и это поможет вам писать более чистый и интуитивный код.
Полезные фрагменты или 30 секунд кода на Python
В этой статье вы найдете полезные фрагменты кода на Python, которые сможете понять менее чем за 30 секунд и применять на практике.
1) Chunk
Разбиение массива на меньшие списки указанного размера. Для создания списка желаемого размера используется range, а заполняется список при помощи map.
from math import ceil def chunk(arr, size): return list( map(lambda x: arr[x * size:x * size + size], list(range(0, ceil(len(arr) / size)))))
Пример:
chunk ([1,2,3,4,5],2) # [[1,2],[3,4],5]
2) Compact
Удаление ложных значений (False, None, 0, и «») из списка при помощи filter().
def compact(arr): return list(filter(lambda x: bool(x), arr))
Пример:
compact([0, 1, False, 2, '', 3, 'a', 's', 34]) # [ 1, 2, 3, 'a', 's', 34 ]
3) Count_by
Этот кусок кода на Python группирует элементы списка и возвращает количество элементов в каждой группе.
Используется map() для сопоставления значений списка со значениями функции. За каждую итерацию счетчик увеличивается.
def count_by(arr, fn=lambda x: x): key = {} for el in map(fn, arr): key[el] = 0 if el not in key else key[el] key[el] += 1 return key
Пример:
from math import floor count_by([6.1, 4.2, 6.3], floor) # {4: 1, 6: 2} count_by(['one', 'two', 'three'], len) # {3: 2, 5: 1}
4) Сount_occurences
Считает количество повторений заданного значения.
Используется функция reduce из встроенных модулей functools для увеличения счетчика каждый раз, когда вы сталкиваетесь с определенным значением внутри списка.
from functools import reduce def count_occurences(arr, val): return reduce( (lambda x, y: x + 1 if y == val and type(y) == type(val) else x + 0), arr)
Пример:
count_occurrences([1, 1, 2, 1, 2, 3], 1) # 3
5) deep_flatten
Выравнивание списка при помощи рекурсии. Используется list.extend() вместе с пустым массивом (result) и функция spread для сглаживания каждого элемента списка.
def spread(arg): ret = [] for i in arg: if isinstance(i, list): ret.extend(i) else: ret.append(i) return ret def deep_flatten(arr): result = [] result.extend( spread(list(map(lambda x: deep_flatten(x) if type(x) == list else x, arr)))) return result
Пример:
deep_flatten([1, [2], [[3], 4], 5]) # [1,2,3,4,5]
6) difference
Возвращает разницу между двумя массивами. Создает set из b и сохраняет только те значения, которые не содержатся в b.
def difference(a, b): b = set(b) return [item for item in a if item not in b]
Пример:
difference([1, 2, 3], [1, 2, 4]) # [3]
7) difference_by
Возвращает разницу между двумя списками, после применения функции к обоим спискам. Создает set, применяя fn к каждому элементу в b, затем использует сочетание fn и a, чтобы сохранить только значения, не содержащиеся в ранее созданном set.
def difference_by(a, b, fn): b = set(map(fn, b)) return [item for item in a if fn(item) not in b]
Пример:
from math import floor difference_by([2.1, 1.2], [2.3, 3.4],floor) # [1.2] difference_by([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], lambda v : v['x']) # [ { x: 2 } ]
8) insertion_sort
На самом базовом уровне алгоритм сортировки вставкой содержит логику смещения и вставки элементов для сортировки неупорядоченного списка любого размера. Способ, который реализует вставку элементов, делает сортировку очень интересной!
def insertion_sort(arr): for i in range(1, len(arr)): key = arr[i] j = i - 1 while j >= 0 and key < arr[j]: arr[j + 1] = arr[j] j -= 1 arr[j + 1] = key
Пример:
arr = [7,4,9,2,6,3] insertionsort(arr) print('Sorted %s' %arr) # sorted [2, 3, 4, 6, 7, 9]
9) shuffle
Рандомизирует порядок значений списка, возвращая новый список. Использует алгоритм Фишера-Йейтса для изменения порядка элементов списка.
from copy import deepcopy from random import randint def shuffle(arr): temp_arr = deepcopy(arr) m = len(temp_arr) while (m): m -= 1 i = randint(0, m) temp_arr[m], temp_arr[i] = temp_arr[i], temp_arr[m] return temp_arr
Пример:
foo = [1,2,3] shuffle(foo) # [2,3,1] , foo = [1,2,3]
10) spread
Заимствует [].concat(…arr) из Javascript. Сглаживает список (не глубоко) и возвращает новый список.
def spread(arg): ret = [] for i in arg: if isinstance(i, list): ret.extend(i) else: ret.append(i) return ret
Пример:
spread([1,2,3,[4,5,6],[7],8,9]) # [1,2,3,4,5,6,7,8,9]
11) zip
Создает список элементов, группируя их на основании позиции в оригинальном списке. Используется max вместе с list comprehension для получения длины самого длинного списка в аргументах. В качестве длины lists используется значение fill_value. По умолчанию значение fill_value равно None.
def zip(*args, fillvalue=None): max_length = max([len(arr) for arr in args]) result = [] for i in range(max_length): result.append([ args[k][i] if i < len(args[k]) else None for k in range(len(args)) ]) return result
Пример:
zip(['a', 'b'], [1, 2], [True, False]) # [['a', 1, True], ['b', 2, False]] zip(['a'], [1, 2], [True, False]) # [['a', 1, True], [None, 2, False]] zip(['a'], [1, 2], [True, False], fill_value = '_') # [['a', 1, True], ['_', 2, False]]
Продолжаем список фрагментов кода на Python реализацией некоторых математических функций.
1) average
Возвращает среднее от двух и более чисел. Происходит деление на len(args) суммы всех элементов args. Второй аргумент 0.0 используется для операций с плавающей точкой в python2.
def average(*args): return sum(args, 0.0) / len(args)
Пример:
average(*[1, 2, 3]) # 2.0 average(1, 2, 3) # 2.0
2) factorial
Вычисляется факториал числа.
Используется рекурсия. Если num меньше или равно 1, возвращается 1, а иначе – произведение num и factorial из num — 1. Сработает исключение, если num будет отрицательным или числом с плавающей точкой.
def factorial(num): if not ((num >= 0) & (num % 1 == 0)): raise Exception( f"Number( {num} ) can't be floating point or negative ") return 1 if num == 0 else num * factorial(num - 1)
Пример:
factorial(6) # 720
3) gcd
Вычисляется наибольший общий делитель между двумя или более числами / списками.
В helperGcdfunction используется рекурсия. Базовый случай, когда y равно 0. В этом случае возвращается x. В противном случае возвращается y и остаток от деления x/y. Используется reduce из встроенного модуля functools.
from functools import reduce def spread(arg): ret = [] for i in arg: if isinstance(i, list): ret.extend(i) else: ret.append(i) return ret def gcd(*args): numbers = [] numbers.extend(spread(list(args))) def _gcd(x, y): return x if not y else gcd(y, x % y) return reduce((lambda x, y: _gcd(x, y)), numbers)
Пример:
gcd(8,36) # 4
4) lcm
Возвращает наименьшее общее кратное из двух или более чисел. Используется формула greatest common divisor (GCD) и lcm(x,y) = x * y / gcd(x,y) для определения наименьшего общего кратного. Формула GCD использует рекурсию, а также reduce из встроенного модуля functools.
from functools import reduce def spread(arg): ret = [] for i in arg: if isinstance(i, list): ret.extend(i) else: ret.append(i) return ret def lcm(*args): numbers = [] numbers.extend(spread(list(args))) def _gcd(x, y): return x if not y else _gcd(y, x % y) def _lcm(x, y): return x * y / _gcd(x, y) return reduce((lambda x, y: _lcm(x, y)), numbers)
Пример:
lcm(12, 7) # 84 lcm([1, 3, 4], 5) # 60
5) max_n
Возвращает n максимальных элементов из списка. Если n больше или равно длине списка, возвращается исходный список, отсортированный в порядке убывания.
Используется list.sort() в сочетании с функцией deepcopy из встроенного модуля copy, чтобы создать клон списка и отсортировать его в порядке возрастания, а затем list.reverse(), чтобы отсортировать по убыванию. Для получения указанного количества элементов используется [:n]. Второй аргумент n опускается, чтобы получить одноэлементный массив.
from copy import deepcopy def max_n(arr, n=1): numbers = deepcopy(arr) numbers.sort() numbers.reverse() return numbers[:n]
Пример:
max_n([1, 2, 3]) # [3] max_n([1, 2, 3], 2) # [3,2]
6) min_n
Возвращает n минимальных элементов из списка. Если n больше или равно длине списка, возвращается исходный список, отсортированный в порядке возрастания.
Используется list.sort() в сочетании с функцией deepcopy из встроенного модуля copy, чтобы создать клон списка и отсортировать его в порядке возрастания, а затем list.reverse(), чтобы отсортировать по убыванию. Для получения указанного количества элементов используется [:n]. Второй аргумент n опускается, чтобы получить одноэлементный массив.
from copy import deepcopy def min_n(arr, n=1): numbers = deepcopy(arr) numbers.sort() return numbers[:n]
Пример:
min_n([1, 2, 3]) # [1] min_n([1, 2, 3], 2) # [1,2]
Последние фрагменты кода на Python на тему работы со строками.
1) byte_size
Возвращает длину строки в байтах. Заданная строка кодируется utf-8, а потом находится ее длина.
def byte_size(string): return(len(string.encode('utf-8')))
Пример:
byte_size('?') # 4 byte_size('Hello World') # 11
2) capitalize
Делает первую букву строки заглавной.
Делает первую букву строки заглавной, а затем добавляет ее к остальной части строки. Параметр lower_rest опускается, чтобы сохранить остальную часть строки нетронутой, или для нее устанавливается значение true, чтобы преобразовать в нижний регистр.
def capitalize(string, lower_rest=False): return string[:1].upper() + (string[1:].lower() if lower_rest else string[1:])
Пример:
capitalize('fooBar') # 'FooBar' capitalize('fooBar', True) # 'Foobar'
3) capitalize_every_word
Делает первую букву заглавной каждого слова строки. Используется str.title.
def capitalize_every_word(string): return string.title()
Пример:
capitalize_every_word('hello world!') # 'Hello World!'
4) count_vowels
Возвращает number гласных в string. При помощи регулярного выражения, вычисляется количество гласных (A, E, I, O, U) в строке.
import re def count_vowels(str): return len(len(re.findall(r'[aeiou]', str, re.IGNORECASE)))
Пример:
count_vowels('foobar') # 3 count_vowels('gym') # 0
5) decapitalize
Делает первую букву строки строчной, а затем добавляет ее к остальной части строки. Параметр upper_rest опускается, чтобы сохранить остальную часть строки нетронутой, или для нее устанавливается значение true, чтобы преобразовать в верхний регистр.
def decapitalize(string, upper_rest=False): return str[:1].lower() + (str[1:].upper() if upper_rest else str[1:])
Пример:
decapitalize('FooBar') # 'fooBar' decapitalize('FooBar', True) # 'fOOBAR'
6) is_lower_case
Преобразует строку в верхний регистр при помощи метода str.lower() и сравнивает ее с оригиналом.
def is_lower_case(str): return str == str.lower()
Пример:
is_lower_case('abc') # True is_lower_case('a3@$') # True is_lower_case('Ab4') # False
7) is_upper_case
Преобразует строку в нижний регистр при помощи метода str.upper() и сравнивает ее с оригиналом.
def is_upper_case(str): return str == str.upper()
Пример:
is_upper_case('ABC') # True is_upper_case('a3@$') # True is_upper_case('aB4') # False
8) palindrome
Возвращает True если строка является палиндромом, иначе False.
Преобразует строку str.lower() и использует re.sub для удаления не алфавитно-цифровых символов. Потом сравнивает новую строку с реверсивной строкой.
def palindrome(string): from re import sub s = sub('[\W_]', '', string.lower()) return s == s[::-1]
Пример:
palindrome('taco cat') # True
Оригинал
Путеводитель по Python. Пишем великолепный код / Хабр
Доброго времени суток, Хабрахабр. Сегодня на крыле принес еще один перевод я (pdf-ки гугловского стайл гайда выложены). Хотя, кто знает, если кто-то оценит сию работу — быть может появится и продолжение. Как-то днём одним, предложил мне мой широко известный в узких кругах коллега scraplesh почитать ресурс — The Hitchhiker’s Guide to Python! называемый. Ресурс этот понравился мне. Понравились советы выдаваемые там. Понравилась канва повествования и вообще понравилось направление мысли автора. А если что-то хорошо на Ваш вкус, то нужно передавать это из уст в уста:) Итак, решил я сделать перевод данного ресурса. Но не всё так сразу — сначала будет пробная статья «на отклик» хабрасообщества. Если уважаемым гикам понравится сия тематика и изложение — будем стараться выпускать новые части. На первый «отклик» я выбрал раздел — «Writing Great Code» и в нем два подпункта «Structure is Key» и «Modules». Откликнемся под катом.
Но перед тем, как окунуться с головой в чужие мысли относительно любимого Python, нужно представить собственно автора ресурса. Зовут его Kenneth Reitz. Как я понял по собранной информации — он профессиональный фотограф (об этом мы можем узнать на его личном сайте), евангелист языка Python и просто гуру разного рода разработки. Работает он на данный момент (по неподтвержденным данным) в Heroku. Так же перепризываю всех форкать его проект на гитхаб.
Фотография Кеннета
Kenneth Reitz на PyCon в Австралии (2012)
Далее — собственно сама статья. (При обнаружении ошибок, как водится — сразу кричите о них! Ошибки требуют исправления.)
Структурируйте свой проект
Под структурой мы подразумеваем решения, которые Вы приняли в отношении того, как Ваш проект сможет достичь поставленных целей. Мы должны рассмотреть как лучше использовать функциональные особенности языка Python, чтобы писать чистый и эффективный код. С практической точки зрения, понятие «структура» означает создание (написание) чистого когда в котором, логика и зависимости так же ясны как организация файлов и папок в файловой системе.
Какие функции должны быть перемещены в какие модули? Как пойдет поток данных через проект? Какие особенности и функции могут быть сгруппированы вместе и изолированы? Отвечая на подобные вопросы, Вы можете начать планировать как будет выглядеть готовый продукт.
В данном разделе мы внимательнее посмотрим на систему модулей и импортов в Python, т.к. они являются центральным элементом в обеспечении структурирования Вашего проекта. Затем, мы обсудим различные точки зрения о том, как построить код, который может быть расширен и надежно протестирован.
Структура решает
Благодаря тому, что импорты и модули обрабатываются в Python, сравнительно просто структурировать проект написанный на этом языке. Слово «просто», в данном контексте означает, что Вы не будете создавать лишних ограничений, и то, что модель импортируемого модуля легко понять. Таким образом, Вам остается сконцентрироваться на чисто архитектурной задаче, а именно трудиться над созданием различных частей Вашего проекта и их взаимодействии.
Просто структурированный проект — означает, что также просто можно создать и плохо структурированный проект. Некоторые признаки плохо структурированного проекта:
- Множественные и грязные циклические зависимости. Если Ваши классы
Table
иChair
нуждаются в импорте классаCarpenter
из модуляworkers.py
, для того, чтобы ответить на вопросtable.isdoneby()
, и наоборот, если классCarpenter
нуждается в импорте классаTable
и классаChair
, чтобы ответить на вопросcarpenter.whatdo()
— Вы получаете циклическую зависимость. В этом случае Вам придется прибегнуть к хитрым уловкам, таким как использование оператора импорта внутри методов или функций. - Скрытые связи. Все и каждое изменение в классе
Table
проваливает 20 тестов в несвязанных тестах, т.к. оно извращает выполнение кода классаCarpenter
, который требует хирургически тонкого адаптивного изменения кода. Это означает, что у Вас слишком много «договоренностей» относительно класса Table в коде классаCarpenter
или наоборот. - Интенсивное использование глобального пространства имен или контекста. Вместо явной передачи (высота, ширина, тип, дерево) друг другу переменных классами
Table
иCarpenter
, Вы полагаетесь на глобальные переменные, которые могут быть изменены и модифицированы на лету разными «товарищами». Вы должны внимательно изучить все места, откуда можно получить доступ к этим глобальным переменным, чтобы понять, почему прямоугольный стол стал квадратным и обнаружить, что удаленный код так же подвергся изменению в данном контексте, подменив размеры стола. - Спагетти-код. Несколько страниц вложенных друг в друга конструкций
if
и цикловfor
с большим количеством повторяющегося кода и вообще не сегментированного, известного как спагетти, кода. Благодаря значащим отступам в Python (одной из самых обсуждаемых особенностей), очень сложно писать такой код на данном языке. Так что есть хорошие новости — Вы не будете наблюдать такой код часто. - Равиоли-код. Такой код более типичен для Python. Он состоит из сотен одинаковых (или подобных друг другу) кусочков логики, классов или объектов без надлежащей структуризации. Если Вы никак не можете запомнить не использовать
FurnitureTable
,AssetTable
илиTable
, или дажеTableNew
для решения Вашей задачи — Вы будете купаться в равиоли-коде.
Модули
Модули в Python являются одним из основных слоев абстракции которые доступны, и, вероятно, являются наиболее нативными для языка. Уровни абстракции позволяют разделить код на части обрабатывающие соответствующие данные и содержащие какой-либо функционал.
Например, один слой проекта может обрабатывать взаимодействие с пользователем, в то время как другой будет обрабатывать манипулирование данными на низком уровне. Наиболее естественный способ разделить эти два уровня — это поместить всю функциональность в один файл, а все низкоуровневые операции в другой. В таком случае интерфейсный файл будет нуждаться в импорте файла с низкоуровневым функционалом. Это делается с помощью выражений import
и from ... import
.
Как только Вы начинаете использовать выражение import — Вы начинаете использовать модули. Это могут быть встроенные модули, такие как os
и sys
, сторонние модули, которые Вы установили в свою среду, или внутренние модули Вашего проекта.
Чтобы придерживаться стиля руководства, старайтесь давать модулям короткие имена, содержащие только буквы нижнего регистра и уверяться, что Вы не используете специальные символы, такие как точка (.) или знак вопроса (?). Так как имя файла подобное my.spam.py, Вы должны избегать. Именование таким образом будет мешать Python искать модули.
В данном примере Python ожидает найти «spam.py
» в папке по имени «my
«, которой не существует. Существует пример того, как точечная нотация должна быть использована в документах Python.
Если Вы хотите, Вы можете назвать файл my_spam.py
, но даже нашего друга — Подчеркивание — не стоит часто использовать в именах модулей.
Помимо некоторых ограничений именования, ничего больше не требуется файлу чтобы стать Python-модулем, но механизм импорта необходимо понимать для того, чтобы использовать эту концепцию должным образом и избежать некоторых проблем.
Откровенно говоря, оператор импорта будет искать соответствующий файл module.py в той же директории, где находится импортирующий файл. Если он не будет найден, интерпретатор Python будет искать module.py
в переменной «path
» рекурсивно и возбудит исключение ImportError
, если последний не будет найден.
После того, как module.py
будет найден, интерпретатор Python выполнит модуль в изолированной области видимости. Любое объявление верхнего уровня в файле module.py
будет выполнено, включая вложенные импорты, если таковые имеются. Объявления функций и классов сохранятся в словарь модуля.
Затем переменные модуля, функции и классы будут доступны для вызова через пространство имен модуля — центральное понятие в программировании, которое особенно мощно и полезно в языке Python.
Во многих языках, файл включается напрямую используя препроцессор чтобы найти весь код в файле и «скопировать» его в код вызывающего модуля. Это отличается от поведения языка Python, в котором подключаемый код изолирован в области видимости своего модуля, что означает, что Вы можете не беспокоиться о том, что включение кода может иметь нежелательные последствия, например, переопределение существующих функций с тем же именем.
Это позволяет моделировать более стандартное поведение с помощью специального синтаксиса выражения import: from module import *
. Обычно это считается плохой практикой. Использование «import *
» делает код трудным для чтения и делает зависимости менее разобщенными.
Использование from module import func
это способ точно указать функцию, которую вы хотите импортировать и поместить в глобальную область видимости. А так же это менее вредно для кода нежели «import *
«, т.к. тут ясно видно что импортируется в глобальную область видимости, преимущество более простой записи import module заключается в экономии нажатий клавиш.
# Very bad
[...]
from modu import *
[...]
x = sqrt(4) # Is sqrt part of modu? A builtin? Defined above?
# Better
from modu import sqrt
[...]
x = sqrt(4) # sqrt may be part of modu, if not redefined in between
# Best
import modu
[...]
x = modu.sqrt(4) # sqrt is visibly part of modu's namespace
Как указано в разделе о стиле, читаемость является одной из главных особенностей Python. Читаемость означает уход от использования бесполезного текстового наполнения и беспорядка в коде, поэтому обычно некоторые усилия тратятся на попытки достичь определенного уровня краткости кода. Но лаконичность и простота имеют определенные пределы, где сокращение кода должно прекратиться. Будучи в состоянии сразу сказать где начинается тот или иной класс или функция, как и идеология module.func
, которая значительно улучшает читаемость кода и его прозрачность во всех, кроме самых простых, отдельных стоящий проектов «в одном файле».
Пишем игру на Python
Прежде чем мы начнём программировать что-то полезное на Python, давайте закодим что-нибудь интересное. Например, свою игру, где нужно не дать шарику упасть, типа Арканоида. Вы, скорее всего, играли в детстве во что-то подобное, поэтому освоиться будет просто.
Логика игры
Есть игровое поле — простой прямоугольник с твёрдыми границами. Когда шарик касается стенки или потолка, он отскакивает в другую сторону. Если он упадёт на пол — вы проиграли. Чтобы этого не случилось, внизу вдоль пола летает платформа, а вы ей управляете с помощью стрелок. Ваша задача — подставлять платформу под шарик как можно дольше. За каждое удачное спасение шарика вы получаете одно очко.
Алгоритм
Чтобы реализовать такую логику игры, нужно предусмотреть такие сценарии поведения:
- игра начинается;
- шарик начинает двигаться;
- если нажаты стрелки влево или вправо — двигаем платформу;
- если шарик коснулся стенок, потолка или платформы — делаем отскок;
- если шарик коснулся платформы — увеличиваем счёт на единицу;
- если шарик упал на пол — выводим сообщение и заканчиваем игру.
Хитрость в том, что всё это происходит параллельно и независимо друг от друга. То есть пока шарик летает, мы вполне можем двигать платформу, а можем и оставить её на месте. И когда шарик отскакивает от стен, это тоже не мешает другим объектам двигаться и взаимодействовать между собой.
Получается, что нам нужно определить три класса — платформу, сам шарик и счёт, и определить, как они реагируют на действия друг друга. Поле нам самим определять не нужно — для этого есть уже готовая библиотека. А потом в этих классах мы пропишем методы — они как раз и будут отвечать за поведение наших объектов.
Весь кайф в том, что мы всё это задаём один раз, а потом объекты сами разбираются, как им реагировать друг на друга и что делать в разных ситуациях. Мы не прописываем жёстко весь алгоритм, а задаём правила игры — а для этого классы подходят просто идеально.
По коням, пишем на Python
Для этого проекта вам потребуется установить и запустить среду Python. Как это сделать — читайте в нашей статье.
Начало программы
Чтобы у нас появилась графика в игре, используем библиотеку Tkinter. Она входит в набор стандартных библиотек Python и позволяет рисовать простейшие объекты — линии, прямоугольники, круги и красить их в разные цвета. Такой простой Paint, только для Python.
Чтобы создать окно, где будет видна графика, используют класс Tk(). Он просто делает окно, но без содержимого. Чтобы появилось содержимое, создают холст — видимую часть окна. Именно на нём мы будем рисовать нашу игру. За холст отвечает класс Canvas(), поэтому нам нужно будет создать свой объект из этого класса и дальше уже работать с этим объектом.
Если мы принудительно не ограничим скорость платформы, то она будет перемещаться мгновенно, ведь компьютер считает очень быстро и моментально передвинет её к другому краю. Поэтому мы будем искусственно ограничивать время движения, а для этого нам понадобится модуль Time — он тоже стандартный.
Последнее, что нам глобально нужно, — задавать случайным образом начальное положение шарика и платформы, чтобы было интереснее играть. За это отвечает модуль Random — он помогает генерировать случайные числа и перемешивать данные.
Запишем всё это в виде кода на Python:
# подключаем графическую библиотеку
from tkinter import *
# подключаем модули, которые отвечают за время и случайные числа
import time
import random
# создаём новый объект — окно с игровым полем. В нашем случае переменная окна называется tk, и мы его сделали из класса Tk() — он есть в графической библиотеке
tk = Tk()
# делаем заголовок окна — Games с помощью свойства объекта title
tk.title('Game')
# запрещаем менять размеры окна, для этого используем свойство resizable
tk.resizable(0, 0)
# помещаем наше игровое окно выше остальных окон на компьютере, чтобы другие окна не могли его заслонить
tk.wm_attributes('-topmost', 1)
# создаём новый холст — 400 на 500 пикселей, где и будем рисовать игру
canvas = Canvas(tk, width=500, height=400, highlightthickness=0)
# говорим холсту, что у каждого видимого элемента будут свои отдельные координаты
canvas.pack()
# обновляем окно с холстом
tk.update()
Мы подключили все нужные библиотеки, сделали и настроили игровое поле. Теперь займёмся классами.
Шарик
Сначала проговорим словами, что нам нужно от шарика. Он должен уметь:
- задавать своё начальное положение и направление движение;
- понимать, когда он коснулся платформы;
- рисовать сам себя и понимать, когда нужно отрисовать себя в новом положении (например, после отскока от стены).
Этого достаточно, чтобы шарик жил своей жизнью и умел взаимодействовать с окружающей средой. При этом нужно не забыть о том, что каждый класс должен содержать конструктор — код, который отвечает за создание нового объекта. Без этого сделать шарик не получится. Запишем это на Python:
# Описываем класс Ball, который будет отвечать за шарик
class Ball:
# конструктор — он вызывается в момент создания нового объекта на основе этого класса
def __init__(self, canvas, paddle, score, color):
# задаём параметры объекта, которые нам передают в скобках в момент создания
self.canvas = canvas
self.paddle = paddle
self.score = score
# цвет нужен был для того, чтобы мы им закрасили весь шарик
# здесь появляется новое свойство id, в котором хранится внутреннее название шарика
# а ещё командой create_oval мы создаём круг радиусом 15 пикселей и закрашиваем нужным цветом
self.id = canvas.create_oval(10,10, 25, 25, fill=color)
# помещаем шарик в точку с координатами 245,100
self.canvas.move(self.id, 245, 100)
# задаём список возможных направлений для старта
starts = [-2, -1, 1, 2]
# перемешиваем его
random.shuffle(starts)
# выбираем первый из перемешанного — это будет вектор движения шарика
self.x = starts[0]
# в самом начале он всегда падает вниз, поэтому уменьшаем значение по оси y
self.y = -2
# шарик узнаёт свою высоту и ширину
self.canvas_height = self.canvas.winfo_height()
self.canvas_width = self.canvas.winfo_width()
# свойство, которое отвечает за то, достиг шарик дна или нет. Пока не достиг, значение будет False
self.hit_bottom = False
# обрабатываем касание платформы, для этого получаем 4 координаты шарика в переменной pos (левая верхняя и правая нижняя точки)
def hit_paddle(self, pos):
# получаем кординаты платформы через объект paddle (платформа)
paddle_pos = self.canvas.coords(self.paddle.id)
# если координаты касания совпадают с координатами платформы
if pos[2] >= paddle_pos[0] and pos[0] <= paddle_pos[2]:
if pos[3] >= paddle_pos[1] and pos[3] <= paddle_pos[3]:
# увеличиваем счёт (обработчик этого события будет описан ниже)
self.score.hit()
# возвращаем метку о том, что мы успешно коснулись
return True
# возвращаем False — касания не было
return False
# обрабатываем отрисовку шарика
def draw(self):
# передвигаем шарик на заданные координаты x и y
self.canvas.move(self.id, self.x, self.y)
# запоминаем новые координаты шарика
pos = self.canvas.coords(self.id)
# если шарик падает сверху
if pos[1] <= 0:
# задаём падение на следующем шаге = 2
self.y = 2
# если шарик правым нижним углом коснулся дна
if pos[3] >= self.canvas_height:
# помечаем это в отдельной переменной
self.hit_bottom = True
# выводим сообщение и количество очков
canvas.create_text(250, 120, text='Вы проиграли', font=('Courier', 30), fill='red')
# если было касание платформы
if self.hit_paddle(pos) == True:
# отправляем шарик наверх
self.y = -2
# если коснулись левой стенки
if pos[0] <= 0:
# движемся вправо
self.x = 2
# если коснулись правой стенки
if pos[2] >= self.canvas_width:
# движемся влево
self.x = -2
Платформа
Сделаем то же самое для платформы — сначала опишем её поведение словами, а потом переведём в код. Итак, вот что должна уметь платформа:
- двигаться влево или вправо в зависимости от нажатой стрелки;
- понимать, когда игра началась и можно двигаться.
А вот как это будет в виде кода:
# Описываем класс Paddle, который отвечает за платформы
class Paddle:
# конструктор
def __init__(self, canvas, color):
# canvas означает, что платформа будет нарисована на нашем изначальном холсте
self.canvas = canvas
# создаём прямоугольную платформу 10 на 100 пикселей, закрашиваем выбранным цветом и получаем её внутреннее имя
self.id = canvas.create_rectangle(0, 0, 100, 10, fill=color)
# задаём список возможных стартовых положений платформы
start_1 = [40, 60, 90, 120, 150, 180, 200]
# перемешиваем их
random.shuffle(start_1)
# выбираем первое из перемешанных
self.starting_point_x = start_1[0]
# перемещаем платформу в стартовое положение
self.canvas.move(self.id, self.starting_point_x, 300)
# пока платформа никуда не движется, поэтому изменений по оси х нет
self.x = 0
# платформа узнаёт свою ширину
self.canvas_width = self.canvas.winfo_width()
# задаём обработчик нажатий
# если нажата стрелка вправо — выполняется метод turn_right()
self.canvas.bind_all('<KeyPress-Right>', self.turn_right)
# если стрелка влево — turn_left()
self.canvas.bind_all('<KeyPress-Left>', self.turn_left)
# пока игра не началась, поэтому ждём
self.started = False
# как только игрок нажмёт Enter — всё стартует
self.canvas.bind_all('<KeyPress-Return>', self.start_game)
# движемся вправо
def turn_right(self, event):
# будем смещаться правее на 2 пикселя по оси х
self.x = 2
# движемся влево
def turn_left(self, event):
# будем смещаться левее на 2 пикселя по оси х
self.x = -2
# игра начинается
def start_game(self, event):
# меняем значение переменной, которая отвечает за старт
self.started = True
# метод, который отвечает за движение платформы
def draw(self):
# сдвигаем нашу платформу на заданное количество пикселей
self.canvas.move(self.id, self.x, 0)
# получаем координаты холста
pos = self.canvas.coords(self.id)
# если мы упёрлись в левую границу
if pos[0] <= 0:
# останавливаемся
self.x = 0
# если упёрлись в правую границу
elif pos[2] >= self.canvas_width:
# останавливаемся
self.x = 0
Счёт
Можно было не выделять счёт в отдельный класс и каждый раз обрабатывать вручную. Но здесь реально проще сделать класс, задать нужные методы, чтобы они сами потом разобрались, что и когда делать.
От счёта нам нужно только одно (кроме конструктора) — чтобы он правильно реагировал на касание платформы, увеличивал число очков и выводил их на экран:
# Описываем класс Score, который отвечает за отображение счетов
class Score:
# конструктор
def __init__(self, canvas, color):
# в самом начале счёт равен нулю
self.score = 0
# будем использовать наш холст
self.canvas = canvas
# создаём надпись, которая показывает текущий счёт, делаем его нужно цвета и запоминаем внутреннее имя этой надписи
self.id = canvas.create_text(450, 10, text=self.score, font=('Courier', 15), fill=color)
# обрабатываем касание платформы
def hit(self):
# увеличиваем счёт на единицу
self.score += 1
# пишем новое значение счёта
self.canvas.itemconfig(self.id, text=self.score)
Игра
У нас всё готово для того, чтобы написать саму игру. Мы уже провели необходимую подготовку всех элементов, и нам остаётся только создать конкретные объекты шарика, платформы и счёта и сказать им, в каком порядке мы будем что делать.
Смысл игры в том, чтобы не уронить шарик. Пока этого не произошло — всё движется, но как только шарик упал — нужно показать сообщение о конце игры и остановить программу.
Посмотрите, как лаконично выглядит код непосредственно самой игры:
# создаём объект — зелёный счёт
score = Score(canvas, 'green')
# создаём объект — белую платформу
paddle = Paddle(canvas, 'White')
# создаём объект — красный шарик
ball = Ball(canvas, paddle, score, 'red')
# пока шарик не коснулся дна
while not ball.hit_bottom:
# если игра началась и платформа может двигаться
if paddle.started == True:
# двигаем шарик
ball.draw()
# двигаем платформу
paddle.draw()
# обновляем наше игровое поле, чтобы всё, что нужно, закончило рисоваться
tk.update_idletasks()
# обновляем игровое поле, и смотрим за тем, чтобы всё, что должно было быть сделано — было сделано
tk.update()
# замираем на одну сотую секунды, чтобы движение элементов выглядело плавно
time.sleep(0.01)
# если программа дошла досюда, значит, шарик коснулся дна. Ждём 3 секунды, пока игрок прочитает финальную надпись, и завершаем игру
time.sleep(3)
# подключаем графическую библиотеку
from tkinter import *
# подключаем модули, которые отвечают за время и случайные числа
import time
import random
# создаём новый объект — окно с игровым полем. В нашем случае переменная окна называется tk, и мы его сделали из класса Tk() — он есть в графической библиотеке
tk = Tk()
# делаем заголовок окна — Games с помощью свойства объекта title
tk.title('Game')
# запрещаем менять размеры окна, для этого используем свойство resizable
tk.resizable(0, 0)
# помещаем наше игровое окно выше остальных окон на компьютере, чтобы другие окна не могли его заслонить. Попробуйте :)
tk.wm_attributes('-topmost', 1)
# создаём новый холст — 400 на 500 пикселей, где и будем рисовать игру
canvas = Canvas(tk, width=500, height=400, highlightthickness=0)
# говорим холсту, что у каждого видимого элемента будут свои отдельные координаты
canvas.pack()
# обновляем окно с холстом
tk.update()
# Описываем класс Ball, который будет отвечать за шарик
class Ball:
# конструктор — он вызывается в момент создания нового объекта на основе этого класса
def __init__(self, canvas, paddle, score, color):
# задаём параметры объекта, которые нам передают в скобках в момент создания
self.canvas = canvas
self.paddle = paddle
self.score = score
# цвет нужен был для того, чтобы мы им закрасили весь шарик
# здесь появляется новое свойство id, в котором хранится внутреннее название шарика
# а ещё командой create_oval мы создаём круг радиусом 15 пикселей и закрашиваем нужным цветом
self.id = canvas.create_oval(10,10, 25, 25, fill=color)
# помещаем шарик в точку с координатами 245,100
self.canvas.move(self.id, 245, 100)
# задаём список возможных направлений для старта
starts = [-2, -1, 1, 2]
# перемешиваем его
random.shuffle(starts)
# выбираем первый из перемешанного — это будет вектор движения шарика
self.x = starts[0]
# в самом начале он всегда падает вниз, поэтому уменьшаем значение по оси y
self.y = -2
# шарик узнаёт свою высоту и ширину
self.canvas_height = self.canvas.winfo_height()
self.canvas_width = self.canvas.winfo_width()
# свойство, которое отвечает за то, достиг шарик дна или нет. Пока не достиг, значение будет False
self.hit_bottom = False
# обрабатываем касание платформы, для этого получаем 4 координаты шарика в переменной pos (левая верхняя и правая нижняя точки)
def hit_paddle(self, pos):
# получаем кординаты платформы через объект paddle (платформа)
paddle_pos = self.canvas.coords(self.paddle.id)
# если координаты касания совпадают с координатами платформы
if pos[2] >= paddle_pos[0] and pos[0] <= paddle_pos[2]:
if pos[3] >= paddle_pos[1] and pos[3] <= paddle_pos[3]:
# увеличиваем счёт (обработчик этого события будет описан ниже)
self.score.hit()
# возвращаем метку о том, что мы успешно коснулись
return True
# возвращаем False — касания не было
return False
# метод, который отвечает за движение шарика
def draw(self):
# передвигаем шарик на заданный вектор x и y
self.canvas.move(self.id, self.x, self.y)
# запоминаем новые координаты шарика
pos = self.canvas.coords(self.id)
# если шарик падает сверху
if pos[1] <= 0:
# задаём падение на следующем шаге = 2
self.y = 2
# если шарик правым нижним углом коснулся дна
if pos[3] >= self.canvas_height:
# помечаем это в отдельной переменной
self.hit_bottom = True
# выводим сообщение и количество очков
canvas.create_text(250, 120, text='Вы проиграли', font=('Courier', 30), fill='red')
# если было касание платформы
if self.hit_paddle(pos) == True:
# отправляем шарик наверх
self.y = -2
# если коснулись левой стенки
if pos[0] <= 0:
# движемся вправо
self.x = 2
# если коснулись правой стенки
if pos[2] >= self.canvas_width:
# движемся влево
self.x = -2
# Описываем класс Paddle, который отвечает за платформы
class Paddle:
# конструктор
def __init__(self, canvas, color):
# canvas означает, что платформа будет нарисована на нашем изначальном холсте
self.canvas = canvas
# создаём прямоугольную платформу 10 на 100 пикселей, закрашиваем выбранным цветом и получаем её внутреннее имя
self.id = canvas.create_rectangle(0, 0, 100, 10, fill=color)
# задаём список возможных стартовых положений платформы
start_1 = [40, 60, 90, 120, 150, 180, 200]
# перемешиваем их
random.shuffle(start_1)
# выбираем первое из перемешанных
self.starting_point_x = start_1[0]
# перемещаем платформу в стартовое положение
self.canvas.move(self.id, self.starting_point_x, 300)
# пока платформа никуда не движется, поэтому изменений по оси х нет
self.x = 0
# платформа узнаёт свою ширину
self.canvas_width = self.canvas.winfo_width()
# задаём обработчик нажатий
# если нажата стрелка вправо — выполняется метод turn_right()
self.canvas.bind_all('<KeyPress-Right>', self.turn_right)
# если стрелка влево — turn_left()
self.canvas.bind_all('<KeyPress-Left>', self.turn_left)
# пока платформа не двигается, поэтому ждём
self.started = False
# как только игрок нажмёт Enter — всё стартует
self.canvas.bind_all('<KeyPress-Return>', self.start_game)
# движемся вправо
def turn_right(self, event):
# будем смещаться правее на 2 пикселя по оси х
self.x = 2
# движемся влево
def turn_left(self, event):
# будем смещаться левее на 2 пикселя по оси х
self.x = -2
# игра начинается
def start_game(self, event):
# меняем значение переменной, которая отвечает за старт движения платформы
self.started = True
# метод, который отвечает за движение платформы
def draw(self):
# сдвигаем нашу платформу на заданное количество пикселей
self.canvas.move(self.id, self.x, 0)
# получаем координаты холста
pos = self.canvas.coords(self.id)
# если мы упёрлись в левую границу
if pos[0] <= 0:
# останавливаемся
self.x = 0
# если упёрлись в правую границу
elif pos[2] >= self.canvas_width:
# останавливаемся
self.x = 0
# Описываем класс Score, который отвечает за отображение счетов
class Score:
# конструктор
def __init__(self, canvas, color):
# в самом начале счёт равен нулю
self.score = 0
# будем использовать наш холст
self.canvas = canvas
# создаём надпись, которая показывает текущий счёт, делаем его нужно цвета и запоминаем внутреннее имя этой надписи
self.id = canvas.create_text(450, 10, text=self.score, font=('Courier', 15), fill=color)
# обрабатываем касание платформы
def hit(self):
# увеличиваем счёт на единицу
self.score += 1
# пишем новое значение счёта
self.canvas.itemconfig(self.id, text=self.score)
# создаём объект — зелёный счёт
score = Score(canvas, 'green')
# создаём объект — белую платформу
paddle = Paddle(canvas, 'White')
# создаём объект — красный шарик
ball = Ball(canvas, paddle, score, 'red')
# пока шарик не коснулся дна
while not ball.hit_bottom:
# если игра началась и платформа может двигаться
if paddle.started == True:
# двигаем шарик
ball.draw()
# двигаем платформу
paddle.draw()
# обновляем наше игровое поле, чтобы всё, что нужно, закончило рисоваться
tk.update_idletasks()
# обновляем игровое поле и смотрим за тем, чтобы всё, что должно было быть сделано — было сделано
tk.update()
# замираем на одну сотую секунды, чтобы движение элементов выглядело плавно
time.sleep(0.01)
# если программа дошла досюда, значит, шарик коснулся дна. Ждём 3 секунды, пока игрок прочитает финальную надпись, и завершаем игру
time.sleep(3)
Что дальше
На основе этого кода вы можете сделать свою модификацию игры:
- добавить второй шарик;
- раскрасить элементы в другой цвет;
- поменять размеры шарика; поменять скорость платформы;
- сделать всё это сразу;
- поменять логику программы на свою.
ТОП-15 трюков в Python 3, делающих код понятнее и быстрее
Подборка трюков в Python третьей версии, которая поможет вам при меньших усилиях писать более качественный программный код.
Python – язык программирования с ясным синтаксисом, и многие удобные вещи в силу простоты часто не задерживаются в памяти. При этом самые краткие и красивые решения обычно оказываются наиболее быстрыми. В представленной ниже подборке из 15 трюков в Python вы наверняка встретите приемы, знаний о которых не хватало в определенный момент в вашей практике.
Как бы вы решили задачу объединения списков разной длины без обхода элементов цикла? Вот как это можно сделать с помощью стандартной функции sum:
L = [[1, 2, 3], [4, 5], [6], [7, 8, 9]] print(sum(L, []))
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Пусть и менее краткий, но более эффективный способ – применение модуля itertools:
import itertools L = [[1, 2, 3], [4, 5], [6], [7, 8, 9]] print(list(itertools.chain.from_iterable(L)))
Заметим, что при работе с последовательностями многие полезные решения находятся в модулях стандартной библиотеки collections (контейнерные структуры данных) и itertools (операции над последовательностями). Внимательное прочтение документации модулей освободит вас от многих часов придумывания собственных «велосипедов».
Один из популярных трюков в Python – обмен значениями без создания временной переменной. Способ применим для любого числа переменных.
a, b = 1, 2 print(a, b) a, b = b, a print(a, b)
1 2 2 1
В правой части инструкции присваивания последовательностей допускается указывать любые итерируемые объекты. Главное, чтобы число элементов слева равнялось числу элементов справа. Такое присваивание применяется и для сложных вложенных конструкций:
for ((a, b), c) in [((1, 2), 3), ((4, 5), 6)]: print(a, b, c)
1 2 3 4 5 6
Для указанного в подзаголовке случая в Python 3 есть оператор звездочки – расширенная операция распаковывания последовательности. Переменной со звездочкой присваивается часть списка, содержащая все неприсвоенные элементы, соответствующие этой позиции:
seq = [1, 2, 3, 4] *a, b, c = seq print(a, b, c) a, *b, c = seq print(a, b, c) a, b, *c = seq print(a, b, c) a, b, c, *d = seq print(a, b, c, d) a, b, c, d, *e = seq print(a, b, c, d, e)
[1, 2] 3 4 1 [2, 3] 4 1 2 [3, 4] 1 2 3 [4] 1 2 3 4 []
Подобные операции можно осуществить и при помощи срезов, но такой код выглядит естественнее. Расширенную операцию распаковывания используют и в циклах, когда длина вложенных последовательностей варьируется:
for (a, *b, c) in [(1, 2, 3), (4, 5, 6, 7)]: print(a, b, c)
1 [2] 3 4 [5, 6] 7
В программном коде нередко приходится сталкиваться с конкатенацией строк при помощи знака сложения. Создание строки из списка нескольких подстрок удобнее осуществить при помощи строкового метода join:
a = ["Python", "-", "прекрасный", "язык."] print(" ".join(a))
Пример посложнее с методом join – конвертирование списка чисел в строку:
numbers = [1, 2, 3, 4, 5] print(', '.join(map(str, numbers)))
1, 2, 3, 4, 5
Проверить, являются ли строки анаграммами (например, в результате случайной перестановки букв) поможет класс Counter модуля collections:
from collections import Counter str1 = 'proglib' str2 = 'prgolib' print(Counter(str1) == Counter(str2))
True
Чтобы поменять местами строки и столбцы матрицы, созданной с помощью встроенных типов данных, воспользуйтесь функцией zip:
original = [('a', 'b'), ('c', 'd'), ('e', 'f')] transposed = zip(*original) print(list(transposed))
[('a', 'c', 'e'), ('b', 'd', 'f')]
Если вы регулярно сталкиваетесь с подобными задачами, вместо таких трюков в Python принято использовать библиотеку NumPy.
Среди регулярно используемых трюков в Python – преобразование списка во множество и обратно в список для удаления повторяющихся элементов списка:
items = [2, 2, 3, 3, 1] print(list(set(items)))
[1, 2, 3]
Но множества – это неупорядоченные последовательности. Часто стоит задача сохранить порядок следования элементов. Для этого удобно воспользоваться типом данных OrderedDict из модуля collections:
items = [2, 2, 3, 3, 1] from collections import OrderedDict print(list(OrderedDict.fromkeys(items).keys()))
[2, 3, 1]
Иногда элементы if настолько просты, что кажется излишним тратить на них строки. В этом случае имеет смысл применить тернарный оператор if/else:
A = Y if X else Z
Интерпретатор выполняет выражение Y, если объект X – истина, и Z, если X – ложь. Не злоупотребляйте этим выражением, если X, Y, Z имеют сложную форму записи.
Тернарный оператор можно использовать не только для переменных, но и для функций:
def product(a, b): return a * b def summarize(a, b): return a + b c = True print((product if c else summarize)(3, 4))
12
Следующая инструкция
X = A or B or C or None
присвоит переменной X первый непустой (имеющий истинное значение) объект из множества объектов A, B и С или None, если все предыдущие объекты окажутся пустыми. В простейшем виде эту особенность используют для задания значения по умолчанию:
X = A or default
Аналогичным образом логический оператор and можно применять для нахождения первого ложного значения.
Обращение к несуществующему ключу словаря вызывает исключение. Избежать этого можно, вызывая метод get. В указанном случае метод выдает None (по умолчанию) или заданное значение аргумента.
d = {'a':1, 'b':2} print(d.get('c')) print(d.get('c', 3))
None 3
При создании собственного типа данных на основе словарей обратите внимание на метод __missing__ для возвращения аргумента при отсутствии ключа:
class MyDict(dict): def __missing__(self, key): return key D = MyDict(a=1, b=2) print(D) print(D['a']) print(D['c'])
{'a': 1, 'b': 2} 1 c
Часто указывается, что основное различие Python 2-й и 3-й версий – это скобки после инструкции print. Это же означает, что инструкция print стала функцией, а значит, скобки могут включать какие-то дополнительные аргументы.
Так и есть. В print имеются следующие аргументы:
- строка sep (по умолчанию один пробел), вставляемая между объектами при выводе;
- строка end (по умолчанию \n), добавляемая в конец выводимого текста;
- file (по умолчанию sys.stdout) – любой объект, поддерживающий метод файлов write(string), то есть стандартный поток, файл и др.
Например, если нам не нужно объединять подстроки, а лишь напечатать суммарную строку:
for part in ["prog", "lib", ".io", "\n"]: print(part, end='')
proglib.io
Тот же подход можно практиковать для чтения файлов:
for line in open('script.py'): print(line, end='')
Присвоение аргументу end пустой строки приводит к тому, что строки файла не перемежаются пустыми строками. Иначе при чтении строк файла и использовании end по умолчанию символ окончания строки \n повторялся бы два раза.
Задача нумерации элементов последовательности настолько распространена, что в Python есть соответствующая встроенная функция enumerate:
for i, item in enumerate(['a', 'b', 'c']): print(i, item)
0 a 1 b 2 c
Для тех, кто уже знаком с enumerate, может оказаться новостью, что у функции есть второй аргумент, задающий начальное число:
for i, item in enumerate(['a', 'b', 'c'], 1): print(i, item)
1 a 2 b 3 c
Распространена практика использования словарей в качестве таблиц для хранения данных. Сортировка данных словаря по значениям ключей, а не самим ключам, нередко ставит в тупик. Задача решается довольно просто при помощи соответствующего аргумента функции сортировки:
d = {'яблоки':40, 'апельсины':80, 'бананы':70} print(sorted(d, key=d.get))
['яблоки', 'бананы', 'апельсины']
Вы, конечно, пользовались генераторами списков. Но знаете ли вы о генераторах множеств и словарей?
S = {i**2 for i in range(10)} D = {i: i**2 for i in range(10)} print(S) print(D)
{0, 1, 64, 4, 36, 9, 16, 49, 81, 25} {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
В случае словарей отличие только в парах ключ-значение. Такие генераторы удобны для начальной инициализации значений последовательностей.
Найти самый часто повторяющийся элемент можно с помощью встроенной функции max. Функция max умеет искать наибольшее значение не только для самого итерируемого объекта, но и основываясь на результах применения к нему функции. Преобразовав список во множество (см. трюк 7) и использовав метод count для нахождения числа вхождений элемента в список, получаем:
a = [1, 2, 3, 1, 2, 3, 2, 2, 4, 5, 1] print(max(set(a), key=a.count))
2
Если необходимо найти несколько наиболее часто повторяющихся значений, воспользуйтесь счетчиком Counter из библиотеки collections:
from collections import Counter a = [1, 2, 3, 1, 2, 3, 2, 2, 4, 5, 1] cnt = Counter(a) print(cnt.most_common(3))
[(2, 4), (1, 3), (3, 2)]
Метод most_common выводит список кортежей вида (элемент, число повторений). Аргумент соответствует желаемому числу кортежей. По умолчанию выводится список кортежей для всех элементов переданного списка.
Наверняка вы знаете про Дзен Python, выводимый интерпретатором по команде import this. В третьей версии Python спрятаны и другие «пасхалки»:
import antigravity
import __hello__
Идеальный код на Python | GeekBrains
https://d2xzmw6cctk25h.cloudfront.net/post/1874/og_cover_image/a506edf4057d40f3c75edc3df2ebe823
Главная ошибка новичка: он пишет код и не думает о том, что его будет кто-то читать. Более того, он не берет в расчет, что сам будет вникать в эти строки спустя день, неделю или год. Новичок решает другую задачу: пишет код, который будет работать.
Проблема в том, что если работодатель видит код, но не может сразу его прочитать, остальное уже не важно. Сотрудник с таким стилем кодинга будет создавать проблемы для коллег — значит, компании он не нужен.
У нас уже вышла публикация о том, как написать код для собеседования и получить работу. Мы пошли дальше и задали вопросы об идеальном коде декану Python-факультета GeekUniversity Алексею Петренко. Он рассказал, что в коде выдает джуниора.
Отступы: все разные
В современных языках программирования существует правило: для выделения самостоятельных смысловых логических блоков используют отступы от начала строки. Python ушел дальше всех: отступ является непосредственным атрибутом этого языка программирования, это часть синтаксиса.
Что новички делают не так
- Неправильно выставляют отступы — их код просто не работает.
- Используют неодинаковое количество отступов: в одной функции — два пробела, в другой — все шесть.
- Используют разные клавиши, чтобы создать отступ: в одной функции — клавишу табуляции, в другой — два пробела.
Из-за разных отступов код смотрится некрасиво, а Python ругает за неудачное сочетание пробелов и табуляций.
Решение
Хороший тон — делать отступ четырьмя нажатиями пробела.
Современные среды разработки — например, PyCharm — упрощают жизнь программиста. Нажав клавишу табуляции, автоматически получаете четыре пробела. Вуаля: код оформлен в общепризнанном стиле.
Для языка Python разработан официальный документ PEP-8, в котором прописаны правила красивого кода. Это соглашение всех программистов мира, которые пишут на Python, о том, какой код считать образцовым.
Переменные: непонятные
Рабочий код должен быть читаемым и ясным без личного присутствия автора. Потрудитесь дать понятные имена всем переменным, методам, функциям, которые используете в коде.
Что новички делают не так
- Используют в качестве переменных обычные буквы алфавита: a, b, c, d, — не задумываясь о смысловой нагрузке.
- Называют все переменные любимой буквой, добавляя цифры: а1, а2, а3. Если переменных двадцать, то будет и а20. Понять, какую информацию они хранят, очень сложно.
- Используют строчную переменную l. Разработчики стараются избегать эту букву. Ее не принято использовать не только в Python, но и в других языках программирования, потому что при быстром чтении кода строчную l легко спутать с единицей. Аналогичная путаница возникает с O и 0.
- Записывают переменные транслитом (massiv вместо array).
- Придумывают новые переменные для общепринятых: для названия цикла (в цикле используют переменные i, j, k — именно в таком порядке, от внешнего i до вложенного k), для обозначения осей координат (x, y).
Решение
Очередное правило хорошего кода: каждая переменная должна говорить о том, что она хранит. Для записи информации о человеке логично создать переменную name. Для возраста — age. Заглядывайте в онлайн-словари, чтобы называть переменные правильными английскими словами, понятными большинству программистов в мире. Идеальная переменная понятна и легко читается:
- Если название переменной состоит из нескольких слов, используйте в Python нижнее подчеркивание: переменная со значением максимального размера — max_size.
- Если именуете класс, записывайте каждое слово с заглавной буквы: имя_переменной должно отличаться от ИмениКласса.
Особенность языка Python в том, что он интерпретируемый. Программа не отслеживает, какие имена дает программист переменным, и примет любое имя, даже название функции.
Из этого вытекает еще одна ошибка новичков: они называют переменные так же, как функции.
В Python есть около 70 функций «из коробки»: функция sum() вычисляет сумму всех переданных аргументов, max() ищет максимальное значение. Если программист назовет переменную sum, она будет работать. Но такой переменной он переопределит функцию суммирования — и она сломается.
Пустые строки: отсутствуют или в избытке
Как правило, код джуниора идет сплошным текстом: в каждой строке — очередная строка кода.
Что новички делают не так
- Не разделяют строки кода пустыми строками.
- Отделяют каждую строчку кода пустой строкой.
В обоих случаях код очень сложно прочитать.
Решение
Код принято делить на логические блоки.
К примеру, если запрашивают информацию о пользователе, пишут несколько строк кода и оставляют одну пустую после блока.
Далее идет блок обработки информации. Если он содержит несколько подблоков, их тоже следует отделить пустой строкой.
Перед выводом информации в конце также добавляют пустую строку.
Слишком сжатый код
Что новички делают не так
Такой код сложно отлаживать в больших проектах: его трудно читать, приходится разбираться в том, как он работает.
Решение
Если есть возможность, распишите несколько составных действий в отдельные строки. Лучше потратить две минуты сейчас и сэкономить двадцать минут на чтение этого кода в будущем.
Советы декана начинающим разработчикам
- Ваш код будут читать другие программисты. Всегда думайте о том, как они его воспримут, насколько он будет понятен коллегам.
- Потратьте время на изучение синтаксиса, почитайте стандарты PEP8. Есть англоязычная версия и перевод. Работодатель будет встречать «по одежке»: ваш код должен выглядеть красиво.
- Если Python — не первый для вас язык программирования, повторяйте требования стиля. Когда разработчик пишет, не соблюдая их, возникает путаница: то ли перед нами человек, у которого в голове перемешались все языки программирования, то ли новичок, который вообще ничего не знает о Python.
- Воспользуйтесь командой import this. Это пасхалка от разработчиков: она выводит свод правил хорошего кода. Почаще перечитывайте этот Дзен Python — и ваш код будет идеален.
Придерживаясь этих советов, вы быстро научитесь писать код, который устроит вас, коллег и работодателя.
Примеры программ на языке Python
Примеры программ на языке Python
Примеры программ на языке программирования Python.
В этой статье собраны примеры небольших программ на языке программирования Python, демонстрирующих его синтаксис и некоторые из возможностей.
Нахождение 10 наиболее частых слов на web странице
Данный пример чисто демонстрационный, так как его можно значительно улучшить.
import string # импортируем модуль для работы со строками from urllib2 import urlopen # из модуля urllib2 импортируем функцию urlopen u = urlopen("http://python.org") # открываем URL на чтение words = {} # связываем имя words с пустым словарём # (словарь — неупорядоченный [[ассоциативный массив]]) for line in u.readlines(): # читаем u по строкам line = string.strip(line, " \n") # отбрасываем начальные и конечные пробелы for word in line.split(" "): # режем каждую строку на слова, ограниченные пробелами try: # блок обработки исключений words[word] += 1 # пытаемся увеличить words[word] на единицу except KeyError: # если не получилось (раньше words[word] не было) words[word] = 1 # присваиваем единицу # теперь словарь words содержит частоту встречаемости каждого слова. # Например, words может содержать {"яблоко":5, "апельсин": 12, "груша": 8} pairs = words.items() # делаем из словаря список пар # pairs == [("яблоко",5), ("апельсин",12), ("груша",8)] pairs.sort(lambda a, b: b[1]-a[1]) # сортируем по убыванию второго элемента пары for p in pairs[:10]: # печатаем первые 10 элементов списка print p[0], p[1]
Примеры работы с последовательностями
Иллюстрируют особенности индексации элементов и срезов: при взятии среза нумеруются не сами элементы, а промежутки между ними.
>>> l = ['A', 'B', 'C', 'D', 'E'] # исходный список >>> # 0 1 2 3 4 5 # пронумерованные промежутки между элементами >>> # -5 -4 -3 -2 -1 # нумерация с конца >>> l[0:2] # срез от нулевого до второго промежутка ['A', 'B'] >>> l[1:-2] # срез от второго до второго с конца элемента ['B','C'] >>> l[1::2] # каждый второй элемент начиная с первого ['B', 'D'] >>> l[::-1] # все элементы в обратном порядке ['E', 'D', 'C', 'B', 'A']
Функции подобные range()
поддерживают то же правило:
>>> range(2, 5) [2, 3, 4] >>> range(5) [0, 1, 2, 3, 4]
Реализация перегрузки функций
Это пример простой реализации поддержки перегрузки функций на Python. Она демонстрирует, как, используя уже имеющиеся в Python средства, можно обойти одно из ограничений базовой реализации. Поддерживается минимум возможностей (только фиксированное количество позиционных аргументов, нет именованных аргументов, нет приведения типов (например int -> float
) и т. п.), но работает достаточно быстро.
import sys # для получения объектов из вышележащих фрэймов стека class CannotResolve(Exception):pass # класс исключения для случая ненахождения функции class Resolver(object): # класс, реализующий разрешение на этапе исполнения emess = "Can't found appropriate signature of func %s() for call with" + \ " params %r" # сообщение об ошибке def __init__(self,name): # конструктор self.function_map = {} # словарь, отображающий типы параметров на функции self.default = None # функция по умолчанию self.name = name # имя функции для вывода сообщений об ошибках def __call__(self,*dt): # имитируем функцию, принимающую любое количество # позиционных параметров cls = tuple(map(type,dt)) # создаем tuple из типов переданных аргументов # функция type возвращает тип своего параметра # map вызовет type для каждого элемента из dt try: x = self.function_map[cls] # пытаемся получить функцию из словаря except KeyError: # если подходящей нет, if self.default is not None: # используем функцию по умолчанию x = self.default else: # если её нет - возбуждаем исключение raise CannotResolve(self.emess % (self.name,cls)) return x(*dt) # вызываем функцию и возвращаем результат def overload(*dt): # декоратор для перегрузки в качестве параметров # принимает типы параметров def closure(func): name = func.__name__ # получаем имя функции fr = sys._getframe(1).f_locals.get(name,Resolver(name)) # опускаемся на один шаг вниз по стеку и находим # локальную переменную с именем функции # если же ее нет, то используем новый # Resolver-объект fr.function_map[dt] = func # добавляем новую функцию к словарю # разрешения вызовов return fr return closure def overdef(func): # для создания функции по умолчанию name = func.__name__ # аналогично как и в функции overload fr = sys._getframe(1).f_locals.get(name,Resolver(name)) fr.default = func return fr # теперь воспользуемся полученными декораторами @overdef # это будет функция по умолчанию def f(*dt,**mp): print "Default call" # если нет явного return, то вернется None @overload(int) # единственный параметр - целое def f(x): return x + 1 @overload(str) # единственный параметр - строка def f(x): return x + "1" @overload(str,int) # строка и целое def f(x,y): return x + str(y) print f(1) # напечатает : 2 print f("1") # напечатает : 11 f(2,2) # напечатает : Default call
Управление контекстом выполнения
Следующий пример из PEP343 иллюстрирует применение оператора with
для защиты блока кода от одновременного выполнения двумя потоками:
from __future__ import with_statement # задействует оператор with в коде from contextlib import contextmanager from threading import Lock # Описание менеджера контекста @contextmanager def locked(lock): lock.acquire() try: yield finally: lock.release() # Определение блокировки myLock = Lock() # Применение оператора with locked(myLock): # print "Охраняемый блок кода. Блокировка будет освобождена при любом выходе из этого блока." #
Генератор чисел Фибоначчи
Пример генератора чисел Фибоначчи и его использования:
def fibonacci(max): # генератор (а не функция, т.к. оператор return заменён на yield) a, b = 0, 1 while a < max: yield a # return a, + запоминаем место рестарта для следующего вызова a, b = b, a + b # параллельное присваивание, которое выполняется одновременно и параллельно for n in fibonacci(100): # используем генератор fibonacci() как итератор print n, # печатаем все числа Фибоначчи меньшие 100 через пробел
Альтернативный синтаксис доступа к элементам словаря
Можно определить словарь, который в дополнение к обычному синтаксису доступа к значению по ключу d[key]
может предоставлять синтаксически более наглядный доступ к атрибуту d.key
в случае алфавитно-цифровых ключей:
class Entity(dict): # наследуем класс от __builtin__.dict def __getattr__(self, key): # этот метод будет вызван, если атрибут # с именем key не будет найден у экземпляра класса try: return self[key] # пытаемся вернуть элемент словаря except KeyError, k: # если такого элемента нет, то возбуждаем raise AttributeError, k # исключение AttributeError # по договоренности __getattr__ # не должно возбуждать других исключений def __setattr__(self, key, value): # этот метод будет вызван при присвоении self[key] = value # атрибуту key значения value def __delattr__(self, key): # а этот при удалении атрибута try: # с помощью del mydict.g del self[key] except KeyError, k: raise AttributeError, k def __repr__(self): # используется функцией repr return self.__class__.__name__ + "(" + dict.__repr__(self) + ")" d = Entity(a=1) d.b_100 = 100 assert d.a == d['a'] and d.b_100 == d['b_100']
Функтор с генерацией байтокода
Пример эффективной реализации функтора, основанный на генерации байтокода во время исполнения. Этот пример демонстрирует следующие возможности/особенности Python:
- Возможность реализации специфических средств функционального программирования наработками, уже имеющимися в языке
- Работать с байтокодом в Python достаточно просто
- Зачастую генерация байтокода способна значительно ускорить исполнение.
Это только пример, он реализует всего одну операцию — сложение и имеет несколько других ограничений.
#------------------------------------------------------------------------------- import byteplay # специальный модуль для удобной работы с Python-байтокодом import new # для создания функции во время исполнения import functools # для update_wrapper import inspect # для получения информации о параметрах, принимаемых функцией #------------------------------------------------------------------------------- class FastFunctor(object): def __init__(self,func,code = None): self.func = None # здесь будем хранить результирующую функцию self.ofunc = func # а здесь исходную(original) функцию if code is None: # конструируем байтокод для вызова функции self.code = [(byteplay.LOAD_CONST,func)] rparams = inspect.getargspec(func)[0] # получаем список параметров, принимаемых функцией self.code.extend((byteplay.LOAD_FAST,i) for i in rparams) self.code.append((byteplay.CALL_FUNCTION,len(rparams))) else: # если же функтор создан из другого функтора, # то только копируем переданный байтокод self.code = code # создаем новый объект кода self.ocode = bp.Code.from_code(func.func_code) def __add__(self,obj): # этот метод вызывается для операции '+' code = self.code[:] # копируем байтокод if isinstance(obj,FastFunctor): # если прибавляемый объект - функтор # просто дописываем его код к нашему # после своего исполнения он "оставит" в вершине стека результат code.extend(obj.code) else: # иначе загружаем объект в стек code.append((byteplay.LOAD_CONST,obj)) # дописываем байтокод, складывающий два верхних элемента в стеке code.append((byteplay.BINARY_ADD ,None )) # создаем новый функтор, с байтокодом получения суммы return self.__class__(self.ofunc,code = code) def __call__(self,*dt,**mp): # этот метод будет вызван для операции вызова object() return self.fast()(*dt,**mp) # конструируем и вызываем функцию def fast(self): # конструируем функцию из байтокода if self.func is None: # если функция не была создана раннее code = self.code + [(bp.RETURN_VALUE,None)] # добавляем байтокод возврата oc = self.ocode # создаем объект кода из байтокода и другой информации bin_code = byteplay.Code(code, oc.freevars, oc.args, oc.varargs, oc.varkwargs, oc.newlocals, "<just_code_%s>" % id(self), "<auto_gen_%s>" % id(self), 0, "auto_generated code") # конструируем новую функцию из объекта кода self.func = new.function(bin_code.to_code(),globals()) # после этой операции для всех средств интроспекции # созданная функция будет выглядеть как оригинальная self.func = functools.update_wrapper(self.func,self.ofunc) return self.func
# Ниже представлено тестирование скорости объектов FastFunctor и SlowFunctor
# (статья "Функциональное программирование на Python", см. сноску после блока кода)
# из IPython (для удобства чтения лог немного изменен)
# строки, начинающиеся с "In [XX]:" вводятся, остальные — вывод интерпретатора
In [1]: import fastfunctor
In [2]: func = lambda x : x + 1 # Создаем очень простую функцию
In [3]: vl = 1 # Переменная, для предотвращения оптимизации
In [4]: functor = fastfunctor.Functor(func)
In [5]: %timeit (functor + functor + 1)(vl) # Тестируем "лобовой" способ
1000 loops, best of 3: 661 mks per loop # Очень медленно
In [6]: functor2 = (functor + functor + 1) # Конструируем функтор один раз
In [7]: %timeit functor2(vl) # и тестируем только непосредственно вызов
100000 loops, best of 3: 4.52 mks per loop # Значительно лучше
In [8]: functor3 = (functor + functor + 1).fast() # Получаем результирующую функцию
In [9]: %timeit functor3(vl)
1000000 loops, best of 3: 1.42 mks per loop
In [10]: def of(vl): return x(vl) + x(vl) + 1 # Создаем функцию "вручную"
In [11]: %timeit of(vl)
1000000 loops, best of 3: 1.42 mks per loop # Скорость полностью совпадает со
# скоростью функтора
In [12]: sfunctor = SlowFunctor(func) # Простая реализация функтора
In [13]: sfunctor = sfunctor + sfunctor + 1 #
In [14]: %timeit sfunctor(vl) #
100000 loops, best of 3: 12.6 mks per loop # Примерно в 9 раз медленнее, чем статический
# вариант
Код SlowFunctor можно посмотреть здесь.
Приведенные значения времени следует рассматривать только в сравнении друг с другом.
ipython — расширение интерпретатора Python для интерактивной работы.
Используя эту технику, можно создать полноценный функтор, добавив функции для других операций (__sub__, __div__
и другие) и расширив его на случай нескольких входных функций с разными аргументами.
Транспонирование матрицы
Пример лаконичной реализации операции транспонирования матриц с использованием парадигмы функционального программирования.
from pprint import pprint # модуль pprint используется для удобного вывода на экран matrix = [[0.5, 0, 0, 0, 0], [ 1, 0.5, 0, 0, 0], [ 1, 1, 0.5, 0, 0], [ 1, 1, 1, 0.5, 0], [ 1, 1, 1, 1, 0.5]] matrix_t = list(zip(*matrix)) # непосредственно транспонирование pprint(matrix) pprint(matrix_t)
Вывод:
[[0.5, 0, 0, 0, 0],
[1, 0.5, 0, 0, 0],
[1, 1, 0.5, 0, 0],
[1, 1, 1, 0.5, 0],
[1, 1, 1, 1, 0.5]]
[[0.5, 1, 1, 1, 1],
[0, 0.5, 1, 1, 1],
[0, 0, 0.5, 1, 1],
[0, 0, 0, 0.5, 1],
[0, 0, 0, 0, 0.5]]
25+ примеров реального программного кода Python
Хотите знать, подходят ли вам технологии?
Должен ли ты быть дизайнером, исходя из ВАШИХ сильных сторон? Front-end разработчик? Или даже специалист по цифровому маркетингу? Пройдите нашу 3-минутную викторину, чтобы выяснить, подходит ли вам техническая карьера.
Конечно, к настоящему времени, возможно, вы знаете, что Python — это суперпопулярный язык программирования, используемый всеми, от веб-разработчиков до специалистов по обработке данных и финансовых мастеров (это означает, что после того, как вы изучите Python, двери будут широко открыты , что касается ваших вариантов карьеры tech).Но вам все еще может быть интересно, что именно Python ВЫГЛЯДИТ и как он работает.
До тех пор, пока вы не познакомитесь с языком программирования в действии, трудно понять, что это такое. Мы собрали более 25 примеров кода Python, чтобы показать, как именно Python работает в реальных условиях. Каждый из этих примеров программирования Python включает ссылку на исходный код, поэтому вы можете тестировать и настраивать их по своему усмотрению и, возможно, даже пытаться написать свои собственные примеры на основе того, что вы здесь видите.
И не забудьте подписаться, чтобы узнать, когда новый курс Python от Skillcrush открыт для регистрации!
1. Функция удаления дубликатов
Автоматизация — огромная часть руководства Python и не менее важная часть того, почему программисты так любят этот язык. Когда дело доходит до программирования и веб-разработки (или науки о данных, машинного обучения или любой другой области, в которой используется Python), возможность автоматизировать процессы, которые в противном случае выполнялись бы вручную, является ЧРЕЗВЫЧАЙНЫМ.
Этот скрипт для удаления дубликатов из списков представляет собой простой, но полностью точный пример скрипта Python, демонстрирующий, насколько мощными могут быть функции автоматизации Python.
2. Magic 8 Ball
Встречаюсь ли я, говоря, что в детстве любил Magic 8 Balls? Что ж, если у вас больше нет своего (возможно, потому, что, как и я, вы разбили его, чтобы увидеть, что это за мутная жидкость была внутри), вы можете воссоздать логику 8 Ball с этим классическим примером скрипта Python!
А если Magic 8 Balls не для вас? У вас все еще будет место в первом ряду, чтобы узнать, как Python используется для генерации случайных ответов
с.S. вы также можете настроить этот базовый код, чтобы он служил определенным ответам на определенные входные данные.
3. Переводчик на латынь для свиней
У ouyay peaksay Igpay Atinlay?
Нет ??
Не проблема. С этим скриптом латинского переводчика Python Pig вы быстро научитесь свободно говорить. Опять же, примеры программирования на Python, подобные этому, — забавные намеки на то, что возможно при изучении Python. Автоматические переводы на латынь Pig могут показаться глупыми, но вы можете распространить этот вид сценариев на любой экземпляр, который требует автоматических ответов на определенные входные данные.
4. Используйте Python для отправки электронной почты
Когда вы начнете работать с языками сценариев, такими как Python или JavaScript, вы поймете, какую важную роль они играют во многих веб-функциях, которые мы воспринимаем как должное. Электронные письма — прекрасный тому пример.
Деловая электронная почта полагается на автоматизацию. Например, когда пользователь подписывается на продукт на вашем сайте, вы хотите, чтобы он получил электронное письмо с подтверждением… но вы НЕ хотите планировать и отправлять каждое из этих писем вручную. Разработчики используют языки сценариев, такие как Python, для автоматизации.Примеры кода Python, такие как этот скрипт Python, демонстрируют, как Python может автоматически планировать и отправлять эти электронные письма, чтобы вам не приходилось делать это.
5. Программа преобразования температуры
Есть ли что-нибудь более смущающее, чем кто-то в Европе, говорящий вам, что на улице 32 градуса, и не зная, что жарко, не холодно? Ну, наверное, есть, но все же. К счастью, мы живем в эпоху Интернета, когда веб-приложения позволяют нам преобразовывать такие числа одним нажатием кнопки! Примеры программирования на Python, такие как эта программа преобразования температуры, показывают, как создать сценарий базового сценария преобразования из градусов Цельсия в градусы Фаренгейта (и наоборот), что вы можете воссоздать для автоматизации любых программ преобразования системы.
6. Преобразование км / ч в миль / ч конвертер
Этот пример сценария Python следует той же предпосылке, что и программа преобразования температуры выше, но в данном случае это сценарий Python, используемый для преобразования километров в час в мили в час. Сравните две программы, чтобы понять, как использовать разные методы и входные данные для достижения аналогичного результата.
7. Скрипт наибольшего общего делителя
Мы часто говорим, что индустрия высоких технологий далеко не так сложна математикой, как думают посторонние.Частично это связано с тем, что большую часть тяжелой вычислительной работы за вас выполняют машины. Тем не менее, вам НЕОБХОДИМО сказать машинам, что и как делать, прежде чем отпускать их. (Это звучит как начало классического фильма «Роботы захватывают мир»…). Скрипты Python, подобные этому сценарию величайшего общего делителя, являются прекрасным примером того, как — если вы используете Python для предоставления машинам четкого набора инструкций, — они будут выкладывайте нужные вам вычислительные данные до скончания веков.
8.Поиск на компьютере определенных файлов
Если вы ищете определенный файл или тип файла на компьютере, последнее, что вам нужно, — это поискать и найти свой путь к нему. А это означает, что если вы работаете над приложением или программой, которая должна иметь возможность находить файлы, вам понадобится способ автоматизировать этот процесс. Так как тебе это? Этот пример сценария Python даст вам некоторые подсказки относительно того, что нужно для создания функции для поиска отдельных файлов и файлов определенного типа.
9. Проверьте свой внешний IP-адрес
Необходимость знать, какой у вас внешний IP-адрес, — одна из тех вещей, которые не возникают каждый день… пока это не произойдет. Вот пример сценария Python, который показывает, насколько легко использовать Python для решения этих утомительных задач.
10. Генератор случайных паролей
Пытаетесь создать веб-сайт или мобильное приложение, способное генерировать случайные пароли пользователей? Тогда это сценарий Python для вас! Погрузитесь в этот код и посмотрите, как сгенерировать пароли и как вы можете изменить правила в соответствии со своими собственными требованиями.
11. Запрос имени пользователя
Простые (но эффективные) примеры кода Python (например, этот сценарий для запроса имени пользователя) являются хорошей отправной точкой для создания более сложных сценариев и функций.
12. Калькулятор продуктового магазина
Вот пример скрипта Python, который показывает, насколько полезен Python для повседневных задач. Пытаетесь отслеживать свой бюджет на продукты? Для этого есть сценарий Python! Этот калькулятор бакалеи использует код Python для отслеживания и подсчета стоимости введенных продуктов.
13. Поиск в Твиттере
Вы когда-нибудь пробовали найти отдельный твит из учетной записи Twitter, на которую вы подписаны? Прокрутка, и прокрутка, и прокрутка, и WHOOPS .. случайно оказавшись снова в верхней части страницы? НЕ КРУТО. Пусть этот пример сценария Python упростит вам задачу, автоматизируя эту функцию поиска.
14. Конвертировать в секунды
Продолжая в духе примеров программирования Python, которые автоматизируют преобразование измерений, этот скрипт Python преобразует часы в секунды… опять же, то, что вы, безусловно, можете сделать вручную, но зачем вам это, если вы знаете, как писать скрипты с Python?
Хотите знать, подходят ли вам технологии?
Должен ли ты быть дизайнером, исходя из ВАШИХ сильных сторон? Front-end разработчик? Или даже специалист по цифровому маркетингу? Пройдите нашу 3-минутную викторину, чтобы выяснить, подходит ли вам техническая карьера.
15. Валик для игры в кости
Будь то настольная игра или ночь в казино дома, и у вас закончились кости, или вам просто нужно случайное число, сгенерированное от 1 до 6 (или любой другой диапазон, который вы хотите, если вы настроите код), этот пример сценария Python виртуальные кости катятся при блокировке.
16. Функция удаления гласных
Сохраните этот файл в разделе «Примеры программирования на Python, которые показывают, насколько хорош Python для изоляции определенных данных». Этот сценарий определяет все гласные в текстовом поле и удаляет их.
17. Генератор гипноза
Вы становитесь очень сонными … нет, не потому, что у вас 17 записей в этом списке, а потому, что вы только что проверили этот пример скрипта Python — генератор гипноза! Да, это звучит как шутка, НО если вы изучите этот код, вы увидите, как использовать Python для определения приоритетов данных и получения разных результатов из одного и того же пула данных в зависимости от ваших параметров.
18. Угадайка
В этом списке есть и другие примеры геймифицированного кода Python, но этот скрипт Python добавляет дополнительный элемент. Конечно, он генерирует случайное число, которое пользователю предлагается угадать, но он также включает цикл, который заставляет скрипт повторяться ДО ТОГО, как пользователь фактически вводит правильное число.
19. Решение Fizz Buzz
А вот и ваше стандартное решение для шипения. Подождите, вы не понимаете, что это значит? Я тоже, но не в этом суть этого примера скрипта Python.Этот сценарий печатает числа от 1 до 100, но для кратных 3 печатает «Fizz» вместо числа, а для кратных 5 печатает «buzz». И этот момент ЭТОГО является еще одним уроком возможностей Python по изоляции и преобразованию данных.
20. Цветовые градиенты и посредники
Этот удобный пример скрипта Python показывает, как использовать Python для вычисления такой неуловимой информации о цвете, как градиенты и посредники.
21. Функция «Получить все ссылки на веб-сайты»
Вам когда-нибудь давали задание найти все ссылки на определенном веб-сайте, и вы начинали видеть двойное изображение, когда вы внимательно изучали экран, чтобы убедиться, что вы ничего не пропустите? Прелесть сценариев на Python в том, что вместо этого вы могли бы просто запустить этот пример сценария Python и автоматически извлекать каждую ссылку из моря данных.
22. Калькулятор средней оценки
Этот очень простой пример скрипта Python просит пользователей ввести три оценки, а затем быстро выдает среднее значение. Конечно, вы можете добавить больше чисел, изменив код (а также более сложные математические функции), но это дает представление о вычислительной мощности Python.
23. Игра с палачами
О, палач. Игра, в которую в юности играли на салфетках и детском меню во время еды. Этот пример сценария Python разбирает механику игры «Палач» и превращает ее в цифровой сеанс угадывания переменных.
24. Устройство реверсирования номера
Мы продолжаем наш список примерами программирования на Python, в которых подчеркивается веселье с числами. Этот скрипт реверса номера Python будет реверсировать любое заданное число. Итак, 1234 становится 4321.
25. Вывести нечетные числа в заданном диапазоне
Это еще один простой случай использования Python для автоматизации задачи, выполнение которой вручную было бы скучным и длительным. Ищете список нечетных чисел в заданном диапазоне? Просто выполните этот пример скрипта Python и БУМ! Миссия выполнена.
26. Выведите все целые числа, которые не делятся ни на 2, ни на 3 и лежат между 1 и 50
Готовы к примерам кода Python, которые становятся еще более дикими с их математическими параметрами? Если вы хотите вывести все целые числа, которые не делятся ни на 2, ни на 3 (И лежат между 1 и 50), хорошо, мой друг, это сценарий Python для вас!
.
Советы по программированию на Python — важные для начинающих и опытных
Вы устали читать длинные уроки Python? Возможно, да. Затем вы должны ознакомиться с коллекцией из десяти лучших советов по программированию на Python, описанных в этом посте. Это результат тщательного исследования и качественной фильтрации.
Такие качественные советы и рекомендации не только помогают тем, кто в них нуждается для быстрой подготовки к собеседованию, но и решают проблемы тех, кто работает над живыми проектами. Причина, по которой эти советы так полезны, потому что мы храним их в архиве в качестве основных с тех пор, как начали изучать Python.
К вашему сведению, мы тщательно проверили все советы по кодированию Python, прежде чем добавлять их в это сообщение. И это всего лишь первый набор советов и приемов, которыми мы делимся сегодня. Будет больше таких сообщений для разработчиков и инженеров по тестированию, которые помогут советами.
Лучшие советы по написанию кода на Python для тестировщиков и программистов
Все наши советы по кодированию работают как с версиями Python 2.x, так и с версией 3.x.
Для наших читателей, которые планируют собеседование по Python, мы предлагаем им прочитать наши недавно опубликованные сообщения о программировании на Python, которые заключаются в следующем.
# Расширенное программирование на Python — 30 советов для всех пользователей Python.
#Want to Crack Your Python Interview — прочтите это.
#Python Programming Quiz — рекомендуется для начинающих и опытных пользователей Python.
Давайте теперь углубимся в десять основных советов по программированию на Python, особенно для тестировщиков и новичков в программировании на Python. Эти советы могут оказаться полезными даже для опытных пользователей.
Советы по программированию на Python — важные для начинающих и опытных
1.Запуск скриптов Python.
В большинстве систем UNIX вы можете запускать сценарии Python из командной строки следующим образом.
# запустить скрипт Python $ python MyFirstPythonScript.py
2. Запуск программ Python из интерпретатора Python.
Интерактивный интерпретатор Python очень прост в использовании. Вы можете попробовать свои первые шаги в программировании и использовать любую команду Python.
Вы вводите команду в консоли Python одну за другой, и ответ сразу же.
Консоль
Python можно запустить, введя команду:
# запустить консоль Python $ питон >>> <введите команды здесь>
В этой статье весь код, начинающийся с символа >>>, предназначен для ввода в командной строке Python. Также важно помнить, что Python очень серьезно относится к вкладкам, поэтому, если вы получаете какую-либо ошибку, в которой упоминаются вкладки, исправьте интервал табуляции.
3. Использование функции enumerate ().
Функция enumerate () добавляет счетчик к повторяемому объекту.
Итерируемый объект — это объект, имеющий метод __iter__, который возвращает итератор. Он может принимать последовательные индексы, начиная с нуля, и вызывает ошибку IndexError , когда индексы больше не действительны.
Типичным примером функции enumerate () является перебор списка и отслеживание индекса. Для этого мы могли бы использовать переменную count. Но Python дает нам более удобный синтаксис для этого с помощью функции enumerate ().
# Сначала подготавливаем список строк subject = ('Python', 'Кодирование', 'Советы') для i, тема в перечислении (темы): печать (я, тема)
# Вывод: 0 Python 1 Кодирование 2 подсказки
4. Тип данных SET.
Тип данных «набор» — это своего рода коллекция. Он был частью Python с версии 2.4.
Набор содержит неупорядоченный набор уникальных и неизменяемых объектов.Это один из типов данных Python, который является реализацией
Этот факт объясняет, почему наборы, в отличие от списков или кортежей, не могут иметь несколько экземпляров одного и того же элемента.
Если вы хотите создать набор, используйте встроенную функцию set () с последовательностью или другим итерируемым объектом.
# *** Создайте набор со строками и выполните поиск в наборе objects = {"python", "кодирование", "советы", "для", "новичков"} # Набор для печати.печать (объекты) печать (len (объекты)) # Использование ключевого слова "in". если «подсказки» в предметах: print ("Это лучшие советы по программированию на Python.") # Использование ключевого слова "не в". если «подсказок по Java» нет в объектах: print («Это лучшие советы по программированию на Python, а не на Java».)
# ** Вывод {'python', 'кодирование', 'советы', 'для', 'начинающих 5 Это лучшие советы по программированию на Python. Это лучшие советы по программированию на Python, а не на Java.
# *** Давайте инициализируем пустой набор items = set () # Добавьте три строки. items.add ("Python") items.add ("кодировка") items.add ("подсказки") печать (элементы)
# ** Вывод {'Python', 'кодирование', 'советы'}
5. Динамический набор текста.
В Java, C ++ и других языках со статической типизацией необходимо указать тип данных возвращаемого значения функции, а также тип каждого аргумента функции.С другой стороны, Python — это язык с динамической типизацией. В Python вы не указываете явно типы данных. В зависимости от назначенного вами значения Python отслеживает тип данных внутри себя. Еще одно хорошее определение динамической типизации:
«Имена привязываются к объектам во время выполнения с помощью операторов присваивания. И есть возможность присвоить имя объектам разных типов во время выполнения программы ».
В следующем примере показано, как функция может проверять свои аргументы.И делать разные вещи в зависимости от их типа.
# Тест на динамическую типизацию. из импорта типов * def CheckIt (x): если type (x) == IntType: print ("Вы ввели целое число.") еще: print («Невозможно распознать тип входных данных.») # Выполнить тест динамической печати CheckIt (999) # Выход: # Вы ввели целое число. CheckIt ("999") # Выход: # Невозможно распознать тип входных данных.
6. Операторы == и =.
Python использует «==» для сравнения и «=» для присвоения. Python не поддерживает встроенное назначение. Таким образом, нет шансов случайно присвоить значение, когда вы захотите его сравнить.
7. Условные выражения.
Python позволяет использовать условные выражения. Вот интуитивно понятный способ написания условных операторов в Python. Следуйте приведенному ниже примеру.
# сделать число всегда нечетным число = число, если число% 2, другое число - 1 # Вызвать функцию, если объект не None.data = data.load (), если data не является «пустышкой». print ("Данные собраны", data)
.
классов и объектов Python [с примерами]
Объекты и классы Python
Python — это объектно-ориентированный язык программирования. В отличие от процедурно-ориентированного программирования, где основной упор делается на функции, объектно-ориентированное программирование делает упор на объекты.
Объект — это просто набор данных (переменных) и методов (функций), которые воздействуют на эти данные. Точно так же класс является планом для этого объекта.
Мы можем думать о классе как об эскизе (прототипе) дома.Он содержит все подробности о этажах, дверях, окнах и т. Д. На основе этих описаний мы строим дом. Дом — это объект.
Поскольку многие дома можно построить по чертежу дома, мы можем создать множество объектов из класса. Объект также называется экземпляром класса, а процесс создания этого объекта называется экземпляром .
Определение класса в Python
Как и определения функций в Python начинаются с ключевого слова def, определения классов начинаются с ключевого слова class.
Первая строка внутри класса называется docstring и содержит краткое описание класса. Хотя это не обязательно, это настоятельно рекомендуется.
Вот простое определение класса.
класс MyNewClass:
'' 'Это строка документации. Я создал новый класс ''
перевал
Класс создает новое локальное пространство имен, в котором определены все его атрибуты. Атрибуты могут быть данными или функциями.
В нем также есть специальные атрибуты, которые начинаются с двойного подчеркивания __
.Например, __doc__
дает нам строку документации этого класса.
Как только мы определяем класс, создается новый объект класса с тем же именем. Этот объект класса позволяет нам получать доступ к различным атрибутам, а также создавать экземпляры новых объектов этого класса.
класс Человек:
"Это человек класса"
возраст = 10
def greet (сам):
print ('Привет')
# Вывод: 10
печать (Person.age)
# Вывод: <функция Person.greet>
печать (Person.greet)
# Вывод: 'Это мой второй класс'
печать (Человек.__doc__)
Выход
10 <функция Person.greet по адресу 0x7fc78c6e8160> Это человек класса
Создание объекта в Python
Мы увидели, что объект класса может использоваться для доступа к различным атрибутам.
Его также можно использовать для создания новых экземпляров объекта (создания экземпляров) этого класса. Процедура создания объекта аналогична вызову функции.
>>> harry = Person ()
Это создаст новый экземпляр объекта с именем harry .Мы можем получить доступ к атрибутам объектов, используя префикс имени объекта.
Атрибуты могут быть данными или методом. Методы объекта — это соответствующие функции этого класса.
Это означает, что поскольку Person.greet
является функциональным объектом (атрибутом класса), Person.greet
будет объектом метода.
класс Человек:
"Это человек класса"
возраст = 10
def greet (сам):
print ('Привет')
# создаем новый объект класса Person
harry = Человек ()
# Вывод: <функция Person.приветствовать>
печать (Person.greet)
# Вывод: <связанный метод Person.greet из <__ main __. Объект Person >>
печать (harry.greet)
# Вызов метода объекта greet ()
# Вывод: Привет
harry.greet ()
Выход
<функция Person.greet at 0x7fd288e4e160> <связанный метод Person.greet объекта <__ main __. Person в 0x7fd288e9fa30 >> Привет
Возможно, вы заметили параметр self
в определении функции внутри класса, но мы назвали этот метод просто harry.greet ()
без аргументов. Это все еще работало.
Это потому, что всякий раз, когда объект вызывает свой метод, сам объект передается в качестве первого аргумента. Итак, harry.greet ()
переводится в Person.greet (harry)
.
В общем случае вызов метода со списком из n аргументов эквивалентен вызову соответствующей функции со списком аргументов, который создается путем вставки объекта метода перед первым аргументом.
По этим причинам первым аргументом функции в классе должен быть сам объект.Это условно называется self . Его можно назвать иначе, но мы настоятельно рекомендуем следовать соглашению.
Теперь вы должны быть знакомы с объектом класса, объектом экземпляра, объектом функции, объектом метода и их различиями.
Конструкторы на Python
Функции класса, начинающиеся с двойного подчеркивания __
, называются специальными функциями, так как они имеют особое значение.
Особый интерес представляет функция __init __ ()
.Эта специальная функция вызывается всякий раз, когда создается новый объект этого класса.
Этот тип функций также называется конструкторами в объектно-ориентированном программировании (ООП). Обычно мы используем его для инициализации всех переменных.
класс ComplexNumber:
def __init __ (self, r = 0, i = 0):
self.real = r
self.imag = я
def get_data (сам):
print (f '{self.real} + {self.imag} j')
# Создать новый объект ComplexNumber
num1 = Комплексное число (2, 3)
# Вызвать метод get_data ()
# Выход: 2 + 3j
число1.получить данные()
# Создаем еще один объект ComplexNumber
# и создайте новый атрибут attr
num2 = Комплексное число (5)
num2.attr = 10
# Вывод: (5, 0, 10)
print ((num2.real, num2.imag, num2.attr))
# но объект c1 не имеет атрибута attr
# AttributeError: объект 'ComplexNumber' не имеет атрибута 'attr'
print (num1.attr)
Выход
2 + 3j (5, 0, 10) Отслеживание (последний вызов последний): Файл «<строка>», строка 27, в <модуле> печать (число1.attr) AttributeError: объект «ComplexNumber» не имеет атрибута «attr»
В приведенном выше примере мы определили новый класс для представления комплексных чисел. Он имеет две функции: __init __ ()
для инициализации переменных (по умолчанию — ноль) и get_data ()
для правильного отображения числа.
Интересная вещь, которую следует отметить в предыдущем шаге, заключается в том, что атрибуты объекта могут быть созданы на лету. Мы создали новый атрибут attr для объекта num2 и также прочитали его.Но это не создает этот атрибут для объекта num1 .
Удаление атрибутов и объектов
Любой атрибут объекта можно удалить в любое время с помощью оператора del
. Попробуйте выполнить следующее в оболочке Python, чтобы увидеть результат.
>>> число1 = Комплексное число (2,3)
>>> del num1.imag
>>> num1.get_data ()
Отслеживание (последний вызов последний):
...
AttributeError: объект 'ComplexNumber' не имеет атрибута 'imag'
>>> del ComplexNumber.получить данные
>>> num1.get_data ()
Отслеживание (последний вызов последний):
...
AttributeError: объект «ComplexNumber» не имеет атрибута «get_data»
Мы даже можем удалить сам объект, используя оператор del.
>>> c1 = Комплексное число (1,3)
>>> дель c1
>>> c1
Отслеживание (последний вызов последний):
...
NameError: имя 'c1' не определено
На самом деле все сложнее. Когда мы выполняем c1 = ComplexNumber (1,3)
, в памяти создается новый объект-экземпляр, и имя c1 связывается с ним.
По команде del c1
эта привязка удаляется, а имя c1 удаляется из соответствующего пространства имен. Однако объект продолжает существовать в памяти, и если к нему не привязано другое имя, он позже автоматически уничтожается.
Это автоматическое уничтожение объектов, на которые нет ссылок, в Python также называется сборкой мусора.
Удаление объектов в Python удаляет привязку имени.
Учебник Python
Обучение на примерах
С помощью нашего редактора «Попробуйте сами» вы можете редактировать код Python и просматривать результат.
Щелкните кнопку «Попробуйте сами», чтобы увидеть, как это работает.
Обработка файлов Python
В разделе «Обработка файлов» вы узнаете, как открывать, читать, писать и
удалить файлы.
Обработка файлов Python
Обработка базы данных Python
В нашем разделе базы данных вы узнаете, как получить доступ и работать с базами данных MySQL и MongoDB:
Python Учебное пособие по MySQL
Учебное пособие по Python MongoDB
Упражнения на Python
Примеры Python
Учись на примерах! Этот учебник дополняет все пояснения поясняющими примерами.
Просмотреть все примеры Python
Python Викторина
Проверьте свои навыки Python с помощью викторины.
Python Викторина
Справочник по Python
Вы также найдете полные ссылки на функции и методы:
Справочный обзор
Встроенные функции
Строковые методы
Списки / массивы
Методы словаря
Кортежные методы
Методы установки
Файловые методы
Ключевые слова Python
Исключения Python
Глоссарий Python
Случайный модуль
Модуль запросов
Математический модуль
Модуль CMath
Загрузить Python
Загрузите Python с официального веб-сайта Python:
https: // питон.org
Экзамен по Python — получите свой диплом!
Интернет-сертификация W3Schools
Идеальное решение для профессионалов, которым необходимо совмещать работу, семью и карьеру.
Уже выдано более 25 000 сертификатов!
Получите сертификат »
Сертификат HTML документирует ваши знания HTML.
Сертификат CSS подтверждает ваши знания в области CSS.
Сертификат JavaScript документирует ваши знания JavaScript и HTML DOM.
Сертификат Python документирует ваши знания Python.
Сертификат jQuery подтверждает ваши знания о jQuery.
Сертификат SQL документирует ваши знания SQL.
Сертификат PHP документирует ваши знания PHP и MySQL.
Сертификат XML документирует ваши знания XML, XML DOM и XSLT.
Сертификат Bootstrap документирует ваши знания о среде Bootstrap.
.