Коробка с питоном
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