Интересные заметки и обучающие материалы по Python
Контакт: @paulwinex
⚠️ Рекламу на канале не делаю!⚠️
Хештеги для поиска:
#tricks
#libs
#pep
#basic
#regex
#qt
#django
#2to3
#source
#offtop
Post #211
2.12K
Можно ли создать инстанс класса используя квадратные скобки вместо круглых? 🙄
Казалось бы, чего сложного, делаем метод
Ниже представлен простой пример добавления метода
Теперь используем новый тип как метакласс нашего класса.
Как еще можно это использовать?
🔸 как-либо модифицировать класс и возвращать тоже класс вместо готового инстанса
🔸 возвращать сразу список инстансов. Например, в случаях когда используется срез
🔸 возвращать разные версии классов по имени под разные ситуации, например унаследованные классы с доп. интерфейсом
Начиная с версии 3.7 у появилась возможность сделать тоже самое без мета класса!
В PEP 560 добавили magic-метод
Теперь наш класс будет выглядеть так:
Казалось бы, чего сложного, делаем метод
__getitem__ как classmethod и готовоclass MyClass:
def __init__(self, value):
self.value = value
@classmethod
def __getitem__(cls, item):
return cls(item)
Но нет, такой финт не сработает.>>> inst = MyClass[5]
TypeError: 'type' object is not subscriptable
Тип данного класса не поддерживает такой интерфейс. Чтобы поддерживал, нужно изменять его метакласс.Ниже представлен простой пример добавления метода
__getitem__ в тип класса. class PresetsType(type):
presets = {
'red': '#ff0000',
'green': '#00ff00',
'blue': '#0000ff'}
def __getitem__(self, item):
instance = self(self.presets[item])
return instance
Получилось что-то вроде пресетов, доступных при создании инстанса через квадратные скобки.Теперь используем новый тип как метакласс нашего класса.
class Color(metaclass=PresetsType):
def __init__(self, value):
self.value = value
def __repr__(self):
return f'<Color "{self.value}">'
Можно тестить!# создаём инстанс обычным способом
>>> c1 = Color('#ffb905')
>>> print(c1)
<Color "#ffb905">
# теперь через квадратные скобки
>>> c2 = Color['red']
>>> print(c2)
<Color "#ff0000">
На сколько пример актуальный в реальной работе, решать вам. Но он точно неочевидный😜Как еще можно это использовать?
🔸 как-либо модифицировать класс и возвращать тоже класс вместо готового инстанса
🔸 возвращать сразу список инстансов. Например, в случаях когда используется срез
🔸 возвращать разные версии классов по имени под разные ситуации, например унаследованные классы с доп. интерфейсом
Начиная с версии 3.7 у появилась возможность сделать тоже самое без мета класса!
В PEP 560 добавили magic-метод
__class_getitem__(cls).Теперь наш класс будет выглядеть так:
class Color:#tricks
presets = {
'red': '#ff0000',
'green': '#00ff00',
'blue': '#0000ff'}
def __init__(self, value):
self.value = value
def __repr__(self):
return f'<Color "{self.value}">'
def __class_getitem__(cls, item):
return cls(cls.presets[item])

