Вероятно, мы научились нарезке списков и строк, когда изучали основы Python.
lis = [1,2,3,4,5] print(lis[0:5:2]) # [1, 3, 5] string = 'abcde' print(string[0:5:2]) # ace
В этой статье мы обсудим, как включить это поведение для наших собственных пользовательских классов и объектов.
Магический метод __getitem__
Магический метод __getitem__
определяет, что происходит, когда мы индексируем объект, например. myobject[0]
.
class Dog: def __getitem__(self, index): return index * 10 dog = Dog() print(dog[4]) # 40 print(dog[5]) # 50 print(dog[6]) # 60
В этом примере мы заставляем магический метод __getitem__
просто возвращать index * 10
.
Встроенный объект slice()
Давайте сначала сделаем так, чтобы магический метод __getitem__
возвращал все, что передает пользователь.
class Dog: def __getitem__(self, index): return index dog = Dog() print(dog[0:5:2]) # slice(0, 5, 2) print(dog[0:4:1]) # slice(0, 4, 1)
И если мы попытаемся нарезать объект dog
(например, как мы делаем для нарезки списка), мы получим объект среза, например. slice(0, 5, 2)
или slice(0, 4, 1)
Разбивка объекта slice()
Давайте немного изменим магический метод __getitem__
.
class Dog: def __getitem__(self, index): if type(index) == slice: return index.start, index.stop, index.step return index dog = Dog() print(dog[0:5:2]) # (0, 5, 2) print(dog[100]) # 100
Если мы передаем слайс, мы возвращаем кортеж (slice.start, slice.stop, slice.step)
. Если мы перейдем во что-нибудь еще, например. целое число, мы просто возвращаем все, что передаем.
Объект среза содержит атрибуты .start
.stop
и .step
, к которым у нас есть прямой доступ. Таким образом, мы можем заставить магический метод __getitem__
делать все, что захотим, даже если он занимает срез.
Настройка этого поведения
Допустим, у нас есть объект Dog
dog
, и мы хотим настроить поведение среза — dog[0:5:2]
вернет словарь, содержащий имя собаки, возраст, а также начало, остановку и шаг.
class Dog: def __init__(self, name, age): self.name = name self.age = age def __getitem__(self, index): output = {'name':, self.name, 'age':self.age} if type(index) == slice: output['start'] = index.start output['stop'] = index.stop outupt['step'] = index.step return output dog = Dog('rocky', 4) print(dog[0:5:2]) # {'name':'rocky', 'age':4, 'start':0, 'stop':5, 'step':2}
В некотором смысле, у нас есть абсолютный контроль над этим поведением — мы можем заставить его делать то, что не имеет ничего общего с нарезкой!
Несколько заключительных слов
Если эта история была полезной и вы хотите оказать небольшую поддержку, вы можете:
- Похлопайте 50 раз за эту историю (мне это очень-очень помогает)
- Подпишитесь на членство в Medium, используя мою ссылку (5 долларов в месяц, чтобы читать неограниченное количество историй на Medium)
Настройка моего домашнего офиса: https://zlliu.co/workspace
Получить мои бесплатные электронные книги: https://zlliu.co/books
- 40 практических вопросов по Python для начинающих
- 20 практических вопросов по рекурсии
- Python от нуля к единице