Коробка с питоном
530 subscribers
49 photos
128 links
Заметки от Python-разработчика: сниппеты, обзоры пакетов, новости и другая полезная информация.
Download Telegram
По возможности используйте специальные (магические) методы

Специальные методы позволяют вашему коду быть более выразительным и "питонячим". Этот простой пример на скриншоте покажет вам огромную выгоду от реализации двух специальных методов: __getitem__ и __len__.

Теперь, как и для любой стандартной коллекции вы можете вызвать функцию len(), которая вернет количество карт:
>>> deck = Deck()
>>> len(deck)
36

А что, если мы хотим получить последнюю карту? Для этого у нас реализован __getitem__:
>>>deck[-1]
Card(rank='Т', suit='бубны')

Получить случайную карту в колоде? Не проблема:
>>>import random
>>>random.choice(deck)
Card(rank='8', suit='трефы')

Как видим - использовать специальные методы очень даже выгодно. Как минимум, это открывает вам богатства взаимодействия с стандартной библиотекой и предоставит простой и понятный интерфейс взаимодействия с классом - нет нужды, например, писать метод для получения случайного элемента в массиве.

Код на Github
#std
Тут спрашивают, почему для определения Card использовался "именованный кортеж" - namedtuple из модуля collections, а не класс/словарь или что-то другое.

Сами кортежи представляют собой неизменяемую структуру данных, которая поддерживает складывание в него произвольных объектов. Проще говоря, это такая коробочка в которую мы можем один раз что-то положить и потом достать по мере необходимости:
>>>some_tuple = ("kiriharu", 1, len)
>>>some_tuple
('kiriharu', 1, <built-in function len>)
>>>some_tuple[1]
1
>>>some_tuple[1] = "hello"
TypeError: 'tuple' object does not support item assignment
Мы же наш Card не изменяем, правда?

Доставать рубашку и ранг карты по индексам - не комильфо, код может быстро превратиться в кашу. А вот если бы мы могли сделать Card.rank (вместо Card[0]) - было бы отлично. Это же нам и позволяет сделать namedtuple.
Каждый объект, который сохранен в именованном кортеже может быть доступен через уникальный идентификатор:
>>>Card = collections.namedtuple('Card', ['rank', 'suit'])
>>>card = Card(6, "пики")
>>>c.suit
'пики'
По итогу, если вам...
- Нужно повысить читабельность кода
- Нужен иммутабельный контейнер
- Нужен контейнер которые хешируется и быстро работает

...используйте namedtuple!
#std
Последовательность - это такая коллекция, значения в которой имеют определенный порядок. Последовательность предоставляет индексированный доступ к элементам. Докажем это на примере обычного типа данных - строки:
>>> name = "kiriharu"
>>> name[1]
'i'
Символы в строке хранятся упорядоченно. Так же мы можем получить букву 'i' по индексу 1.

Последовательности бывают:
- Контейнерные - это такие последовательности, в которых можно хранить элементы разных типов. К ним относят list, tuple и deque из модуля collections.
- Плоские - в них можно хранить только элемент 1 типа. Примерами являются str, bytes, bytearray и array из модуля array.
- Мутабельные - содержимое таких последовательностей можно изменять. К ним относятся list, bytearray, array из модуля array, deque из модуля collections.
- Иммутабельные - содержимое таких последовательностей изменять нельзя. К таким относятся tuple, str, bytes.
#std
Множества, в отличии от последовательностей неупорядоченные, элементы в нём уникальны. Поговорим про изменяемые множества.
Допустим, я хочу сделать изменяемое множество из моих братишек-разработчиков (привет!):
>>> bros = {"cmd410", "reygasai", "mo_rjindael"}
>>> bros
{'mo_rjindael', 'cmd410', 'reygasai'}

Добавим ещё одного братишку:
>>> bros.add("hkc")
>>> bros
{'mo_rjindael', 'cmd410', 'reygasai', 'hkc'}

Попытаемся добавить 'cmd410' ещё раз в множество:
>>> bros.add("cmd410")
>>> bros
{'mo_rjindael', 'cmd410', 'reygasai', 'hkc'}

Множество не изменилось, потому что 'cmd410' уже в нём есть. Элементы в множестве уникальны.
Это можно использовать для того, чтобы убрать повторяющиеся элементы в списке:
>>> repeated = [1, 1, 2, 3, 4, 1, 2, 3, 4, 4]
>>> set(repeated)
{1, 2, 3, 4}

Множество неупорядоченно. Например, мы не можем взять нулевого по индексу братишку из него:
>>> bros[0]
TypeError: 'set' object is not subscriptable.

А какие ещё операции над множествами вы знаете? Пишите в комментарии 😏!
#std