Вы используете свойства (@property) в классах? Удобная штука, | Python Заметки
Вы используете свойства (@property) в классах? Удобная штука, скажу я вам! Но работают они только для инстансов класса. Вот простой пример:
class A: @property def prop(self): return 10
Создаём класс и получаем значение свойства
>>> a = A() >>> a.prop 10
А что будет если вызвать свойство у класса
>>> A.prop
Эх, несвезло Как сделать подобие property для класса? Есть несколько способов:
Написать свой декоратор в точности повторяющий функционал property. Это ведь не сложно Я тоже когда-то писал свою версию подобного функционала. Примеры смотрим здесь и здесь .
Всё это здорово, но не очень-то хочется изобретать велосипед. Есть ли что-то готовое из стандартных средств?
Если вы уже перешли на Python 3.9 то можете написать вот так:
class С: @classmethod @property def x(cls): return 2+2
>>> C.x 4
Например, вот так можно динамический докстринг сделать
class C: @classmethod @property def doc(cls) -> str: return f"A doc for {cls.name!r}"
>>> help(C) class C(builtins.object) | A doc for 'C' ...
Хорошая новость в том, что это работает из коробки, ничего дописывать не надо. Плохая новость — не получится сделать setter, по крайней мере лаконично и красиво. Например, вот так не работает:
class C: _x = 0 def x_get(cls): return cls._x def x_set(cls, value): cls._x = value x = classmethod(property(x_get, x_set))
Выражение присвоения просто перезаписывает атрибут x, а не вызывает setter.
>>> C.x = 1 >>> C._x 0
Чтобы setter тоже работал, нужно сделать иначе. Но об этом смотрите в следующем посте.