我想有一个具有属性 attr
的类,当第一次访问时,它运行一个函数并返回一个值,然后变为该值(其类型更改等) .
可以通过以下方式获得类似的行为:
class MyClass(object):
@property
def attr(self):
try:
return self._cached_result
except AttributeError:
result = ...
self._cached_result = result
return result
obj = MyClass()
print obj.attr # First calculation
print obj.attr # Cached result is used
但是, .attr
在执行此操作时不会成为初始结果 . 如果它这样做会更有效率 .
难点在于 obj.attr
设置为属性后,无法轻松设置其他内容,因为无限循环会自然出现 . 因此,在上面的代码中, obj.attr
属性没有setter,因此无法直接修改它 . 如果定义了setter,则在此setter中替换 obj.attr
会创建一个无限循环(从setter中访问setter) . 我还想到了第一次删除setter以便能够使用 del self.attr
进行常规 self.attr = …
,但这会调用属性删除器(如果有的话),这会重新创建无限循环问题( self.attr
的修改通常会通过 property 规则) .
那么,有没有办法绕过属性机制并在 MyClass.attr.__getter__
内用任何东西替换绑定属性 obj.attr
?
2 回答
这看起来有点像过早优化:您希望通过使描述符自身更改来跳过方法调用 .
这是完全可能的,但它必须是合理的 .
要修改属性中的描述符,您必须编辑您的类,这可能不是您想要的 .
我认为实现这一目标的更好方法是:
不定义
obj.attr
覆盖
__getattr__
,如果参数为"attr",obj.attr = new_value
,否则引发AttributeError
设置
obj.attr
后,将不再调用__getattr__
,因为只有在该属性不存在时才会调用它 . (__getattribute__
是一直被调用的那个 . )与初始提议的主要区别在于第一个属性访问速度较慢,因为
__getattr__
的方法调用开销,但它将与常规__dict__
查找一样 .Example :
EDIT : 请参阅the other answer,特别是如果您使用的是Python 3.6或更高版本 .
对于使用描述符协议的新式类,您可以通过创建自己的自定义描述符类来完成此操作,该类最多只能调用一次
__get__()
方法 . 当发生这种情况时,然后通过创建类方法具有相同名称的实例属性来缓存结果 .这就是我的意思 .