什么是惰性属性? [英] What is a lazy property?

查看:78
本文介绍了什么是惰性属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在网上浏览 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__ 方法获取返回值并在实例上设置一个新属性barfoo.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. No bar 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 decorated bar method.

  • The bar method calculates something, and returns the string 'spam'.

  • The cached_property __get__ method takes the return value and sets a new attribute bar 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 the bar 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆