在classmethods上使用property()

问题:

我有一个类有两个类的方法(使用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装饰函数?

回答:

阅读Python 2.2 release笔记,我找到以下内容。

当属性作为类属性(C.x)而不是实例属性(C()。x)访问时,将不会调用get属性的get方法。如果要用作属性的__get__操作用作类属性,则可以将属性子类化 – 它是一种新的类型本身 – 来扩展其__get__方法,也可以通过创建一个新的属性来定义描述符类型定义__get__,__set__和__delete__方法的类的类。

 注意:下面的方法实际上并不适用于setter,只有getter。
因此,我相信规定的解决方案是创建一个ClassProperty作为属性的子类。

class ClassProperty(property):
    def __get__(self, cls, owner):
        return self.fget.__get__(None, owner)()

class foo(object):
    _var=5
    def getvar(cls):
        return cls._var
    getvar=classmethod(getvar)
    def setvar(cls,value):
        cls._var=value
    setvar=classmethod(setvar)
    var=ClassProperty(getvar,setvar)

assert foo.getvar() == 5
foo.setvar(4)
assert foo.getvar() == 4
assert foo.var == 4
foo.var = 3
assert foo.var == 3

但是,设置者实际上并不工作:

foo.var = 4
assert foo.var == foo._var # raises AssertionError

 foo._var不变,您只是用新值覆盖了该属性。
您也可以使用ClassProperty作为装饰器:

class Foo(object):
    _var = 5

    @ClassProperty
    @classmethod
    def var(cls):
        return cls._var

    @var.setter
    @classmethod
    def var(cls, value):
        cls._var = value

assert foo.var == 5

 
 
Code问答: http://codewenda.com/topics/python/
Stackoverflow: Using property() on classmethods

*转载请注明本文链接以及stackoverflow的英文链接

发表评论

电子邮件地址不会被公开。 必填项已用*标注

88 − = 82