Python 3.5 类型提示动态生成的实例属性 [英] Python 3.5 type hinting dynamically generated instance attributes

查看:80
本文介绍了Python 3.5 类型提示动态生成的实例属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想为动态生成的对象属性添加 Python 3.5 类型提示,以便 IDE 正确自动完成它们.这里的动态"是指该属性在类创建期间或 __init__ 或任何其他方法中不存在.

例如有没有办法通过评论或其他技巧来添加这些?如果没有,我可以回退以添加虚拟类属性.

示例::

 类请求:"""示例 HTTP 请求对象.我们有 `get_user()` 但我们没有在任何地方声明它."""...# Pyramid 插入方法和属性来请求的方式,为框架启用插件功能# 添加 Request.user - 在应用程序生命周期的不同部分完成,而不是在类创建期间config.add_request_method(auth.get_user, 'user', reify=True)

我们的目标是让 PyC​​harm 和其他 IDE 能够完成这个属性.

解决方案

在 Python 3.6+ 中,您可以使用类级别的类型提示 - 这些不会在类中生成属性.即

类请求(_Request):用户:可选[用户]

这不会在类中创建属性,只会创建注释.

<预><代码>>>>请求用户回溯(最近一次调用最后一次):文件<stdin>",第 1 行,在 <module> 中AttributeError: 类型对象请求"没有属性用户">>>请求.__注释__{'用户':typing.Union[foo.User, NoneType]}

在 Python 3.5 中,可以创建一个返回非数据描述符的函数(即描述符 without __set__);这将被实例属性覆盖,但它带有一些最小运行时开销 - 描述符将从 __dict__ 获取并检查它是否定义了 __set__槽 - 甚至所有读取.然后它可能看起来像

类请求(_Request):用户 = 输入(用户)

其中 typed 定义为

def typed(type: Type[T]) ->:...返回一个虚拟的非数据描述符...

这应该足以让 PyC​​harm 正确推断类型.

I'd like to add Python 3.5 type hints for dynamically generated object attributes, so that IDEs correctly autocomplete them. Here by "dynamical" I mean that the attribute is not present during class creation or in __init__ or any other method.

E.g. is there a way to add these through comments or other tricks? If not I can fallback to add dummy class attributes.

Example::

 class Request:
      """Example HTTP request object.

      We have `get_user()`  but we do not declare it anyhere.
      """

 ...


 # Pyramid's way of plugging in methods and properties to request, enabled addon capabilities for the framework
 # adds Request.user - done in different part of application lifecycle, not during class creation
 config.add_request_method(auth.get_user, 'user', reify=True)

The goal is to make this work so that PyCharm and other IDEs would complete this attribute.

解决方案

In Python 3.6+ you can use the class-level type hints - these would not generate attributes in the class. I.e.

class Request(_Request):
    user: Optional[User]

This would not create an attribute in the class, only an annotation.

>>> Request.user
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'Request' has no attribute 'user'

>>> Request.__annotations__
{'user': typing.Union[foo.User, NoneType]}

In Python 3.5 it is possible to make a function that returns a non-data descriptor (i.e. a descriptor without __set__); this would be overridable by an instance attribute but it comes with some minimal runtime overhead - the descriptor will be fetched from __dict__ and checked if it defines the __set__ slot - even for all reads. It could then look something like

class Request(_Request):
    user = typed(User)

where the typed is defined as

def typed(type: Type[T]) -> T:
    ... return a dummy non-data-descriptor...

This should be enough for PyCharm to infer the types correctly.

这篇关于Python 3.5 类型提示动态生成的实例属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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