我有一个包含两个类方法的类(使用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
修饰函数一起使用吗?
发布于 2009-11-26 08:58:18
Python >= 3.9
只需同时使用两个装饰器即可。参见this answer。
Python < 3.9
属性是在类上创建的,但会影响实例。因此,如果您需要一个classmethod属性,请在元类上创建该属性。
>>> class foo(object):
... _var = 5
... class __metaclass__(type): # Python 2 syntax for metaclasses
... pass
... @classmethod
... def getvar(cls):
... return cls._var
... @classmethod
... def setvar(cls, value):
... cls._var = value
...
>>> foo.__metaclass__.var = property(foo.getvar.im_func, foo.setvar.im_func)
>>> foo.var
5
>>> foo.var = 3
>>> foo.var
3
但是既然你正在使用一个元类,如果你只是把类方法移到其中,它会读起来更好。
>>> class foo(object):
... _var = 5
... class __metaclass__(type): # Python 2 syntax for metaclasses
... @property
... def var(cls):
... return cls._var
... @var.setter
... def var(cls, value):
... cls._var = value
...
>>> foo.var
5
>>> foo.var = 3
>>> foo.var
3
或者,使用Python3的metaclass=...
语法,在foo
类主体外部定义的元类,以及负责设置_var
的初始值的元类
>>> class foo_meta(type):
... def __init__(cls, *args, **kwargs):
... cls._var = 5
... @property
... def var(cls):
... return cls._var
... @var.setter
... def var(cls, value):
... cls._var = value
...
>>> class foo(metaclass=foo_meta):
... pass
...
>>> foo.var
5
>>> foo.var = 3
>>> foo.var
3
发布于 2012-11-29 19:32:12
我希望这个非常简单的只读@classproperty
装饰器能帮助寻找类属性的人。
class classproperty(object):
def __init__(self, fget):
self.fget = fget
def __get__(self, owner_self, owner_cls):
return self.fget(owner_cls)
class C(object):
@classproperty
def x(cls):
return 1
assert C.x == 1
assert C().x == 1
发布于 2010-03-30 18:07:36
如果你想通过实例化的对象访问class属性,那么只在meta类上设置它是没有帮助的,在这种情况下,你还需要在对象上安装一个普通属性(它会分派给class属性)。我认为下面的内容会更清楚一些:
#!/usr/bin/python
class classproperty(property):
def __get__(self, obj, type_):
return self.fget.__get__(None, type_)()
def __set__(self, obj, value):
cls = type(obj)
return self.fset.__get__(None, cls)(value)
class A (object):
_foo = 1
@classproperty
@classmethod
def foo(cls):
return cls._foo
@foo.setter
@classmethod
def foo(cls, value):
cls.foo = value
a = A()
print a.foo
b = A()
print b.foo
b.foo = 5
print a.foo
A.foo = 10
print b.foo
print A.foo
https://stackoverflow.com/questions/128573
复制相似问题