python - 实现绝地可以理解的惰性属性
问题描述
我一直在使用惰性属性库(https://pypi.org/project/lazy-property/)。它工作得很好,但在我的编辑器中,这些惰性属性不会提供任何自动完成功能。
我的设置是 Atom,使用 ide-python 包 ( https://github.com/lgeiger/ide-python ),它由 python-language-server ( https://github.com/palantir/python-驱动language-server ),它使用 Jedi ( https://github.com/davidhalter/jedi ) 进行自动补全。
基本上,这个问题应该在任何基于 Jedi 的自动完成上下文中都可以重现。
我一直想知道是否有一种方法可以重写惰性属性中的代码(可能使用类型提示等),以便绝地可以理解来自惰性属性装饰方法的类型应该与 if 相同装饰师缺席。
这个装饰器的实现其实超级简单,基本上就是:
class lazy_property(property):
def __init__(self, method, fget=None, fset=None, fdel=None, doc=None):
self.method = method
self.cache_name = f"_{self.method.__name__}"
doc = doc or method.__doc__
super().__init__(fget=fget, fset=fset, fdel=fdel, doc=doc)
update_wrapper(self, method)
def __get__(self, instance, owner):
if instance is None:
return self
if hasattr(instance, self.cache_name):
result = getattr(instance, self.cache_name)
else:
if self.fget is not None:
result = self.fget(instance)
else:
result = self.method(instance)
setattr(instance, self.cache_name, result)
return result
有没有人知道我如何重构这个类以让 Jedi 理解它应该假设装饰器不会改变返回值的类型?
任何帮助将不胜感激,干杯。
解决方案
你的问题是绝地不能真正处理super().__init__(fget=fget, fset=fset, fdel=fdel, doc=doc)
。它并不真正理解你在那里做什么。如果你self.fget = fget
在那一行之后写,绝地会理解你的例子。
为了更深入地挖掘,绝地试图了解分支。在您的情况下,它认为结果result = self.fget(instance)
是它必须推断的,因为self.fget is not None
推断为 True。它推断为True
,因为self.fget
forproperty
在 typeshed 存根中定义为def fget(self) -> Any: ...
,这基本上意味着它肯定存在。因此,在您的情况下,存根基本上与实际情况有所不同(它们在那里可能略有错误)。
但是请注意,编写缓存的属性是以前做过的事情。最好的实现之一是@cached_property
in Django
,因此您也可以从那里复制:
https://docs.djangoproject.com/en/2.2/_modules/django/utils/functional/#cached_property
推荐阅读
- ruby-on-rails - Rails 表单在操作中使用令牌而不是 id
- c# - TextBlock 未显示在 ListView 中
- c++ - 如何避免生产中的 vtable-lookups,并且仍然能够在单元测试中进行广泛的模拟?
- android - 我们可以使用手机的inbuit指纹扫描仪将指纹存储在数据库中吗
- excel - 使用 ADODB 记录集填充组合框
- hyperledger-fabric - 计算超级账本结构中两个配置 protobuf 之间的增量是什么意思?
- google-compute-engine - 在 Google Compute Engine 上设置 dask 和 jupyter
- c# - `nameof()` 在当前上下文中不存在?
- ionic-framework - Ionic(浏览器/iOS)如何检查用户是否已经授予权限?
- amazon-web-services - AWS CodePipeline“需要一个 AppSpec 文件,但在修订版中找不到”