如何在Python中创建只读类属性?

本质上,我想做这样的事情:


class foo:

    x = 4

    @property

    @classmethod

    def number(cls):

        return x

然后,我希望以下工作:


>>> foo.number

4

不幸的是,以上方法不起作用。不是给我,4而是给我<property object at 0x101786c58>。有什么办法可以达到上述目的?


缥缈止盈
浏览 575回答 3
3回答

月关宝盒

在property从一类访问时(即,当描述符总是返回本身instance是None在它的__get__方法)。如果这不是您想要的,则可以编写一个始终使用类对象(owner)而不是实例的新描述符:>>> class classproperty(object):...&nbsp; &nbsp; &nbsp;def __init__(self, getter):...&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;self.getter= getter...&nbsp; &nbsp; &nbsp;def __get__(self, instance, owner):...&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return self.getter(owner)...&nbsp;>>> class Foo(object):...&nbsp; &nbsp; &nbsp;x= 4...&nbsp; &nbsp; &nbsp;@classproperty...&nbsp; &nbsp; &nbsp;def number(cls):...&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return cls.x...&nbsp;>>> Foo().number4>>> Foo.number4

慕后森

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

白板的微信

我同意unubtu的回答;它似乎起作用,但是,它在Python 3上无法使用这种精确的语法(特别是我在努力使用Python 3.4)。看起来这是在Python 3.4下必须形成模式才能使事情起作用的方式:class MetaFoo(type):&nbsp; &nbsp;@property&nbsp; &nbsp;def number(cls):&nbsp; &nbsp; &nbsp; return cls.xclass Foo(metaclass=MetaFoo):&nbsp; &nbsp;x = 4print(Foo.number)# 4Foo.number = 6# AttributeError: can't set attribute
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python