从本质上讲,我想做这样的事情:
class foo:
x = 4
@property
@classmethod
def number(cls):
return x
然后,我希望以下内容能够起作用:
>>> foo.number
4
不幸的是,上面的方法不起作用。它给我的不是4
,而是<property object at 0x101786c58>
。有没有办法做到这一点呢?
发布于 2010-07-08 20:43:55
当从一个类访问时,property
描述符总是返回自身(即,当instance
在其__get__
方法中为None
时)。
如果这不是您想要的,您可以编写一个始终使用类对象(owner
)而不是实例的新描述符:
>>> class classproperty(object):
... def __init__(self, getter):
... self.getter= getter
... def __get__(self, instance, owner):
... return self.getter(owner)
...
>>> class Foo(object):
... x= 4
... @classproperty
... def number(cls):
... return cls.x
...
>>> Foo().number
4
>>> Foo.number
4
发布于 2018-05-25 02:36:46
Mikhail Gerasimov的解决方案是相当完整的。不幸的是,这是一个缺点。如果你有一个使用他的类属性的类,由于带有class Wrapper
的TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
,任何子类都不能使用它。
幸运的是,这是可以修复的。在创建class Meta
时,只继承给定类的元类。
def classproperty_support(cls):
"""
Class decorator to add metaclass to our class.
Metaclass uses to add descriptors to class attributes, see:
http://stackoverflow.com/a/26634248/1113207
"""
# Use type(cls) to use metaclass of given class
class Meta(type(cls)):
pass
for name, obj in vars(cls).items():
if isinstance(obj, classproperty):
setattr(Meta, name, property(obj.fget, obj.fset, obj.fdel))
class Wrapper(cls, metaclass=Meta):
pass
return Wrapper
https://stackoverflow.com/questions/3203286
复制相似问题