По возможности используйте специальные (магические) методы
Специальные методы позволяют вашему коду быть более выразительным и "питонячим". Этот простой пример на скриншоте покажет вам огромную выгоду от реализации двух специальных методов:
Теперь, как и для любой стандартной коллекции вы можете вызвать функцию
Код на Github
#std
Специальные методы позволяют вашему коду быть более выразительным и "питонячим". Этот простой пример на скриншоте покажет вам огромную выгоду от реализации двух специальных методов:
__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!
#std
namedtuple
из модуля collections
, а не класс/словарь или что-то другое.Сами кортежи представляют собой неизменяемую структуру данных, которая поддерживает складывание в него произвольных объектов. Проще говоря, это такая коробочка в которую мы можем один раз что-то положить и потом достать по мере необходимости:
>>>some_tuple = ("kiriharu", 1, len)Мы же наш Card не изменяем, правда?
>>>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.rank
(вместо Card[0]
) - было бы отлично. Это же нам и позволяет сделать namedtuple
.Каждый объект, который сохранен в именованном кортеже может быть доступен через уникальный идентификатор:
>>>Card = collections.namedtuple('Card', ['rank', 'suit'])По итогу, если вам...
>>>card = Card(6, "пики")
>>>c.suit
'пики'
- Нужно повысить читабельность кода
- Нужен иммутабельный контейнер
- Нужен контейнер которые хешируется и быстро работает
...используйте namedtuple!
#std