什么是惰性属性? [英] What is a lazy property?
问题描述
在网上浏览 webapp2 文档时,我发现了关于装饰器的信息:webapp2.cached_property
在文档中,它说:
<块引用>将函数转换为惰性属性的装饰器.
我的问题是:
→ 什么是惰性属性?
它是一个 property
装饰器,在第一次调用后就让开.它允许您自动缓存计算值.
标准库@property
装饰器 是一个数据描述符对象并且总是被调用,即使在同名的实例上有一个属性.
另一方面,@cached_property
装饰器,只有有一个 __get__
方法,这意味着它不会被调用,如果有已存在具有相同名称的属性.它通过在第一次调用时在实例上设置具有相同名称的属性来利用这一点.
给定一个名为 foo
的实例上的 @cached_property
修饰的 bar
方法,会发生以下情况:
Python 解析
foo.bar
.在实例上找不到bar
属性.Python 在类上找到
bar
描述符,并在其上调用__get__
.cached_property
__get__
方法调用修饰的bar
方法.bar
方法计算一些东西,并返回字符串'spam'
.cached_property
__get__
方法获取返回值并在实例上设置一个新属性bar
;foo.bar = '垃圾邮件'
.cached_property
__get__
方法返回'spam'
返回值.如果你再次请求
foo.bar
,Python 会在实例上找到bar
属性,并从这里开始使用它.
另请参阅 源代码:
<块引用># 实现细节:该属性实现为非数据# 描述符.非数据描述符仅在存在时才被调用# 实例的 __dict__ 中没有同名条目.# 这让我们可以彻底摆脱访问函数调用# 高架.如果选择手动调用 __get__ 属性# 仍会按预期工作,因为查找逻辑已复制# 在 __get__ 中用于手动调用.
请注意,从 Python 3.8 开始,标准库有一个类似的对象,@functools.cached_property()
.它的实现更健壮一点,它可以防止以不同的名称意外重用,如果在没有 __dict__
属性的对象上使用或该对象不支持,则会产生更好的错误消息项目分配,也是线程安全的.
While looking through the webapp2 documentation online, I found information on the decorator: webapp2.cached_property
In the documentation, it says:
A decorator that converts a function into a lazy property.
My question is:
→ What is a lazy property?
It is a property
decorator that gets out of the way after the first call. It allows you to auto-cache a computed value.
The standard library @property
decorator is a data descriptor object and is always called, even if there is an attribute on the instance of the same name.
The @cached_property
decorator on the other hand, only has a __get__
method, which means that it is not called if there is an attribute with the same name already present. It makes use of this by setting an attribute with the same name on the instance on the first call.
Given a @cached_property
-decorated bar
method on an instance named foo
, this is what happens:
Python resolves
foo.bar
. Nobar
attribute is found on the instance.Python finds the
bar
descriptor on the class, and calls__get__
on that.The
cached_property
__get__
method calls the decoratedbar
method.The
bar
method calculates something, and returns the string'spam'
.The
cached_property
__get__
method takes the return value and sets a new attributebar
on the instance;foo.bar = 'spam'
.The
cached_property
__get__
method returns the'spam'
return value.If you ask for
foo.bar
again, Python finds thebar
attribute on the instance, and uses that from here on out.
Also see the source code for the original Werkzeug implementation:
# implementation detail: this property is implemented as non-data # descriptor. non-data descriptors are only invoked if there is # no entry with the same name in the instance's __dict__. # this allows us to completely get rid of the access function call # overhead. If one choses to invoke __get__ by hand the property # will still work as expected because the lookup logic is replicated # in __get__ for manual invocation.
Note that as of Python 3.8, the standard library has a similar object, @functools.cached_property()
. It's implementation is a little bit more robust, it guards against accidental re-use under a different name, produces a better error message if used on an object without a __dict__
attribute or where that object doesn't support item assignment, and is also thread-safe.
这篇关于什么是惰性属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!