У меня есть класс с двумя методами класса (используя функцию classmethod ()) для получения и установки того, что по сути является статической переменной. Я пытался использовать функцию property () с ними, но это приводит к ошибке. Мне удалось воспроизвести ошибку со следующим в переводчике:
class Foo(object):
_var = 5
@classmethod
def getvar(cls):
return cls._var
@classmethod
def setvar(cls, value):
cls._var = value
var = property(getvar, setvar)
Я могу продемонстрировать методы класса, но они не работают как свойства:
>>> f = Foo()
>>> f.getvar()
5
>>> f.setvar(4)
>>> f.getvar()
4
>>> f.var
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: 'classmethod' object is not callable
>>> f.var=5
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: 'classmethod' object is not callable
Можно ли использовать функцию property () с декорированными функциями classmethod?
class Foo(metaclass=...)
синтаксиса.Читая заметки о выпуске Python 2.2 , я обнаружил следующее.
ПРИМЕЧАНИЕ. Приведенный ниже метод на самом деле не работает для сеттеров, а только для геттеров.
Поэтому я считаю, что предписанным решением является создание ClassProperty в качестве подкласса свойства.
Однако, сеттеры на самом деле не работают:
foo._var
без изменений, вы просто перезаписали свойство новым значением.Вы также можете использовать
ClassProperty
в качестве декоратора:источник
self.fget(owner)
и устраняете необходимость использовать здесь@classmethod
вообще? (это то, чтоclassmethod
делает , перевести.__get__(instance, owner)(*args, **kwargs)
наfunction(owner, *args, **kwargs)
вызовы через посредника; свойства не нуждаются в посреднике).foo.var = 3
назначение фактически не проходит через свойство , а вместо этого просто заменил объект свойства наfoo
целое число. Если вы добавитеassert isinstance(foo.__dict__['var'], ClassProperty)
вызовы между вашими утверждениями, вы увидите, что сбой послеfoo.var = 3
выполнения.instance.attr
,instance.attr = value
иdel instance.attr
все будет связывать дескриптор найдены наtype(instance)
, но в то время какclassobj.attr
привязки,classobj.attr = value
иdel classobj.attr
ничего не и вместо того, чтобы заменить или удалить сам объект дескриптора). Вам нужен метакласс для поддержки установки и удаления (создание объекта класса экземпляром, а метакласса типом).Я надеюсь, что этот простой и понятный
@classproperty
декоратор только для чтения поможет кому-то искать свойства класса.источник
class D(C): x = 2; assert D.x == 2
.format
как"{x}".format(**dict(self.__class__.__dict__, **self.__dict__))
:(x
права доступа10
. Мне нравится этот подход, потому что он аккуратный и простой, но звучит как антипаттерн__set__
что вызывает,ValueError
чтобы предотвратить переопределение.Нет.
Однако метод класса - это просто связанный метод (частичная функция) класса, доступный из экземпляров этого класса.
Поскольку экземпляр является функцией класса и вы можете извлечь класс из экземпляра, вы можете получить любое желаемое поведение из свойства класса с помощью
property
:Этот код можно использовать для тестирования - он должен пройти без каких-либо ошибок:
И обратите внимание, что нам вообще не нужны метаклассы - и вы в любом случае напрямую не обращаетесь к метаклассу через экземпляры его классов.
написание
@classproperty
декоратораНа самом деле вы можете создать
classproperty
декоратор всего за несколько строк кода, создав подклассыproperty
(он реализован в C, но вы можете увидеть эквивалентный Python здесь ):Затем обработайте декоратор так, как если бы это был метод класса, объединенный со свойством:
И этот код должен работать без ошибок:
Но я не уверен, насколько это было бы хорошо. В старой статье рассылки говорится, что это не должно работать.
Получение свойства для работы в классе:
Недостатком вышеизложенного является то, что «свойство класса» недоступно из класса, поскольку оно просто перезапишет дескриптор данных из класса
__dict__
.Однако мы можем переопределить это с помощью свойства, определенного в метаклассе
__dict__
. Например:И тогда экземпляр класса метакласса может иметь свойство, которое обращается к свойству класса, используя принцип, уже продемонстрированный в предыдущих разделах:
И теперь мы видим как экземпляр
и класс
иметь доступ к свойству класса.
источник
Python 3!
Старый вопрос, множество мнений, крайне нуждающихся в единственно верном Python 3 пути.
К счастью, с
metaclass
kwarg это легко :Затем,
>>> Foo.var
источник
Foo
является экземпляром его метакласса и@property
может использоваться для его методов так же, как и для методов экземпляровFoo
.Foo.__new__
. Хотя в этот момент, возможно, стоит либо вместо этого использовать getattribute, либо задаться вопросом, существует ли претензия в отношении языковой функции - это действительно тот подход, который вы хотите использовать вообще.Нет разумного способа заставить эту систему "свойства класса" работать в Python.
Вот один из необоснованных способов заставить его работать. Вы, конечно, можете сделать его более плавным с увеличением количества магии метаклассов.
Узел проблемы в том, что свойства - это то, что Python называет «дескрипторами». Там нет короткого и легкий способа объяснить , как этот вид Метапрограммирования работ, поэтому я должен указать вам на дескриптор HOWTO .
Вам нужно только когда-либо разбираться в подобных вещах, если вы внедряете довольно продвинутую среду. Например, прозрачная персистентность объектов, система RPC или разновидность языка, специфичного для предметной области.
Тем не менее, в комментарии к предыдущему ответу, вы говорите, что вы
Мне кажется, что вы действительно хотите, это шаблон проектирования Observer .
источник
Установка его только для метакласса не поможет, если вы хотите получить доступ к свойству класса через инстанцированный объект, в этом случае вам также необходимо установить обычное свойство для объекта (который отправляется свойству класса). Я думаю, что следующее немного более понятно:
источник
Половина решения, __set__ в классе не работает, по-прежнему. Решение представляет собой пользовательский класс свойств, реализующий как свойство, так и статический метод.
источник
У вас есть доступ хотя бы к одному экземпляру класса? Тогда я могу придумать, как это сделать:
источник
Попробуйте, это выполнит работу без необходимости изменять / добавлять много существующего кода.
property
Функции необходимы дваcallable
аргумента. дать им лямбда-обертки (которые он передает экземпляр в качестве первого аргумента), и все хорошо.источник
Вот решение, которое должно работать как для доступа через класс, так и для доступа через экземпляр, который использует метакласс.
Это также работает с сеттером, определенным в метаклассе.
источник
После поиска в разных местах я нашел метод для определения свойства класса, допустимого для Python 2 и 3.
Надеюсь, что это может помочь кому-то :)
источник
Вот мое предложение. Не используйте методы класса.
Шутки в сторону.
В чем причина использования методов класса в этом случае? Почему бы не иметь обычный объект обычного класса?
Если вы просто хотите изменить значение, свойство не очень полезно, не так ли? Просто установите значение атрибута и покончите с этим.
Свойство следует использовать только в том случае, если есть что скрывать, что может измениться в будущей реализации.
Может быть, ваш пример урезан, и у вас закончились какие-то адские вычисления. Но это не похоже, что собственность добавляет значительную ценность.
Техники «конфиденциальности» под влиянием Java (в Python имена атрибутов начинаются с _) не очень полезны. Рядовой от кого? Точка приватности немного туманна, когда у вас есть источник (как вы делаете в Python.)
Получающие влияние Java-методы в стиле EJB и сеттеры (часто выполняемые как свойства в Python) предназначены для облегчения примитивного самоанализа Java, а также для прохождения проверки с помощью компилятора статического языка. Все эти методы получения и установки не так полезны в Python.
источник