По возможности используйте специальные (магические) методы
Специальные методы позволяют вашему коду быть более выразительным и "питонячим". Этот простой пример на скриншоте покажет вам огромную выгоду от реализации двух специальных методов:
Теперь, как и для любой стандартной коллекции вы можете вызвать функцию
Код на 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
Последовательность - это такая коллекция, значения в которой имеют определенный порядок. Последовательность предоставляет индексированный доступ к элементам. Докажем это на примере обычного типа данных - строки:
Последовательности бывают:
- Контейнерные - это такие последовательности, в которых можно хранить элементы разных типов. К ним относят
- Плоские - в них можно хранить только элемент 1 типа. Примерами являются
- Мутабельные - содержимое таких последовательностей можно изменять. К ним относятся
- Иммутабельные - содержимое таких последовательностей изменять нельзя. К таким относятся
#std
>>> name = "kiriharu"Символы в строке хранятся упорядоченно. Так же мы можем получить букву 'i' по индексу 1.
>>> name[1]
'i'
Последовательности бывают:
- Контейнерные - это такие последовательности, в которых можно хранить элементы разных типов. К ним относят
list
, tuple
и deque
из модуля collections
.- Плоские - в них можно хранить только элемент 1 типа. Примерами являются
str
, bytes
, bytearray
и array
из модуля array
.- Мутабельные - содержимое таких последовательностей можно изменять. К ним относятся
list
, bytearray
, array
из модуля array
, deque
из модуля collections
.- Иммутабельные - содержимое таких последовательностей изменять нельзя. К таким относятся
tuple
, str
, bytes
.#std
Множества, в отличии от последовательностей неупорядоченные, элементы в нём уникальны. Поговорим про изменяемые множества.
Допустим, я хочу сделать изменяемое множество из моих братишек-разработчиков (привет!):
Это можно использовать для того, чтобы убрать повторяющиеся элементы в списке:
#std
Допустим, я хочу сделать изменяемое множество из моих братишек-разработчиков (привет!):
>>> bros = {"cmd410", "reygasai", "mo_rjindael"}Добавим ещё одного братишку:
>>> bros
{'mo_rjindael', 'cmd410', 'reygasai'}
>>> bros.add("hkc")Попытаемся добавить 'cmd410' ещё раз в множество:
>>> bros
{'mo_rjindael', 'cmd410', 'reygasai', 'hkc'}
>>> bros.add("cmd410")Множество не изменилось, потому что 'cmd410' уже в нём есть. Элементы в множестве уникальны.
>>> bros
{'mo_rjindael', 'cmd410', 'reygasai', 'hkc'}
Это можно использовать для того, чтобы убрать повторяющиеся элементы в списке:
>>> 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