用普通属性替换属性属性(Replace property attribute with a normal attribute)

编程入门 行业动态 更新时间:2024-10-23 15:17:50
用普通属性替换属性属性(Replace property attribute with a normal attribute)

是否有可能用“普通”属性替换对象的属性?

我需要这个,因为当我访问属性的第一个,我想要的属性生成的值。 但之后我不再需要财产:

class A(object): @property def x(self): self.x = "toto" # Replace property, fail because no setter return self.x a = A() print a.x # "toto" a.x = "tata"

我知道我可以将值存储在_x等第二个属性中,并检查属性是否存在_x ,但是我想知道是否有可能替换属性本身。

Is it possible to replace a property of an object with 'normal' attribute?

I need this because when I access the attribute for the first, I want the value to be generated by the property. But I no longer need the property afterward:

class A(object): @property def x(self): self.x = "toto" # Replace property, fail because no setter return self.x a = A() print a.x # "toto" a.x = "tata"

I know I can store the value in a second attribute like _xand check in the property if _x exist but I want to know if it's possible the replace the property itself.

最满意答案

为了避免缺少setter,你必须直接操作实例__dict__字典。 然而,你不能用常规的property对象来做你想做的事情,因为它是一个数据描述符 。 属性访问将始终为实例属性提供数据描述符优先级。

您必须创建一个自定义描述符,而不是定义__set__或__delete__方法:

class CachingProperty(object): def __init__(self, fget): self.name = fget.__name__ self.fget = fget def __get__(self, instance, owner): if instance is None: return self value = self.fget(instance) instance.__dict__[self.name] = value return value

该描述符还负责直接在实例__dict__属性中设置值,从而创建一个实例属性。

使用上面的类而不是property :

class A(object): @CachingProperty def x(self): return "toto"

演示,显示getter方法只被调用一次:

>>> class Demo(object): ... @CachingProperty ... def foo(self): ... print("Calling the foo property") ... return "bar" ... >>> d = Demo() >>> d.foo Calling the foo property 'bar' >>> d.foo 'bar' >>> vars(d) {'foo': 'bar'}

To bypass the lack of a setter, you'd have to directly manipulate the instance __dict__ dictionary. However, you can't do what you want with a regular property object, because it is a data descriptor. Attribute access will always give a data descriptor priority over instance attributes.

You'd have to create a custom descriptor instead, one that doesn't define a __set__ or __delete__ method:

class CachingProperty(object): def __init__(self, fget): self.name = fget.__name__ self.fget = fget def __get__(self, instance, owner): if instance is None: return self value = self.fget(instance) instance.__dict__[self.name] = value return value

This descriptor also takes care of setting the value directly in the instance __dict__ attribute, thus creating an instance attribute.

Use the above class instead of property:

class A(object): @CachingProperty def x(self): return "toto"

Demo, showing that the getter method is only called once:

>>> class Demo(object): ... @CachingProperty ... def foo(self): ... print("Calling the foo property") ... return "bar" ... >>> d = Demo() >>> d.foo Calling the foo property 'bar' >>> d.foo 'bar' >>> vars(d) {'foo': 'bar'}

更多推荐

本文发布于:2023-08-07 11:21:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1464255.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:属性   Replace   property   attribute   normal

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!