3 回答

TA贡献1772条经验 获得超5个赞
在property从一类访问时(即,当描述符总是返回本身instance是None在它的__get__方法)。
如果这不是您想要的,则可以编写一个始终使用类对象(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

TA贡献1802条经验 获得超5个赞
这将成为Foo.number一个只读属性:
class MetaFoo(type):
@property
def number(cls):
return cls.x
class Foo(object, metaclass=MetaFoo):
x = 4
print(Foo.number)
# 4
Foo.number = 6
# AttributeError: can't set attribute
说明:使用@property时的通常情况如下:
class Foo(object):
@property
def number(self):
...
foo = Foo()
中定义的属性Foo对其实例是只读的。也就是说,foo.number = 6将引发一个AttributeError。
类似地,如果要Foo.number提高,则AttributeError需要设置中定义的属性type(Foo)。因此,需要一个元类。
请注意,这种只读性无法避免受到黑客的攻击。可以通过更改Foo的类使该属性可写:
class Base(type): pass
Foo.__class__ = Base
# makes Foo.number a normal class attribute
Foo.number = 6
print(Foo.number)
版画
6
或者,如果您希望设置Foo.number可设置的属性,
class WritableMetaFoo(type):
@property
def number(cls):
return cls.x
@number.setter
def number(cls, value):
cls.x = value
Foo.__class__ = WritableMetaFoo
# Now the assignment modifies `Foo.x`
Foo.number = 6
print(Foo.number)
也打印6。

TA贡献1883条经验 获得超3个赞
我同意unubtu的回答;它似乎起作用,但是,它在Python 3上无法使用这种精确的语法(特别是我在努力使用Python 3.4)。看起来这是在Python 3.4下必须形成模式才能使事情起作用的方式:
class MetaFoo(type):
@property
def number(cls):
return cls.x
class Foo(metaclass=MetaFoo):
x = 4
print(Foo.number)
# 4
Foo.number = 6
# AttributeError: can't set attribute
添加回答
举报