为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

缥缈止盈 2019-12-25 14:42:36
本质上,我想做这样的事情:class foo:    x = 4    @property    @classmethod    def number(cls):        return x然后,我希望以下工作:>>> foo.number4不幸的是,以上方法不起作用。不是给我,4而是给我<property object at 0x101786c58>。有什么办法可以达到上述目的?
查看完整描述

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


查看完整回答
反对 回复 2019-12-25
?
慕后森

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。


查看完整回答
反对 回复 2019-12-25
?
白板的微信

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


查看完整回答
反对 回复 2019-12-25
  • 3 回答
  • 0 关注
  • 574 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号