Python 3.5 类型提示动态生成的实例属性
Python 3.5 type hinting dynamically generated instance attributes
我想为动态生成的对象属性添加 Python 3.5 类型提示,以便 IDE 正确地自动完成它们。 "dynamical" 是指在 class 创建期间或 __init__
或任何其他方法中不存在该属性。
例如有没有办法通过评论或其他技巧添加这些?如果没有,我可以退而求其次添加虚拟 class 属性。
示例::
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)
我们的目标是使这项工作有效,以便 PyCharm 和其他 IDE 可以完成此属性。
我子class编辑了真实的class
我在 class
中添加了伪 __type_hinting__
方法
我用这个class而不是真正的作为参数类型提示
class Request(_Request):
"""
HTTP request class.
This is a Pyramid Request object augmented with type hinting information for Websauna-specific functionality.
To know more about request read also
* py:class:`pyramid.request.Request` documentation
* py:class:`webob.request.Request` documentation
Counterintuitively, this request is also available in non-HTTP applications like command line applications and timed tasks.
These applications do not get request URL from a front end HTTP webserver, but a faux request is constructed pointing to the website URL taken from ``websauna.site_url`` setting.
This is to allow similar design patterns and methodology to be applied in HTTP and non-HTTP applications.
By setting variables in ``__type_hinting__()`` based on arguments types allows IDEs to infer type information when you hint your views as::
from websauna.system.http import Request
def hello_world(request: Request):
request. # <-- When typing, here autocompletion kicks in.
"""
def __type_hinting__(self, user: Optional[User], dbsession: Session, session: ISession, admin: Admin, registry: Registry):
"""
A dummy helper function to tell IDEs about reify'ed variables.
:param user: The logged in user. None if the visitor is anonymous.
:param dbsession: Current active SQLAlchemy session
:param session: Session data for anonymous and logged in users.
:param admin: The default admin interface of the site. Note that the site can have several admin interfaces for different purposes.
:param registry: Pyramid registry's. E.g.
:py:attr:`pyramid.registry.Registry.settings` for reading settings and :py:meth:`pyramid.registry.Registry.notify` for sending events.
"""
self.user = user
self.dbsession = dbsession
self.session = session
self.admin = admin
self.registry = registry
在 Python 3.6+ 中,您可以使用 class-level 类型提示 - 这些不会在 class 中生成属性。即
class Request(_Request):
user: Optional[User]
这不会在 class 中创建属性,只会创建注释。
>>> 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]}
在 Python 3.5 中可以创建一个 returns 一个 non-data 描述符的函数(即 没有 __set__
);这将被实例属性覆盖,但它带有 一些最小的 运行时开销 - 将从 __dict__
获取描述符并检查它是否定义了 __set__
插槽- 即使是所有阅读。它可能看起来像
class Request(_Request):
user = typed(User)
其中 typed
定义为
def typed(type: Type[T]) -> T:
... return a dummy non-data-descriptor...
这应该足以 PyCharm 正确推断类型。
我想为动态生成的对象属性添加 Python 3.5 类型提示,以便 IDE 正确地自动完成它们。 "dynamical" 是指在 class 创建期间或 __init__
或任何其他方法中不存在该属性。
例如有没有办法通过评论或其他技巧添加这些?如果没有,我可以退而求其次添加虚拟 class 属性。
示例::
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)
我们的目标是使这项工作有效,以便 PyCharm 和其他 IDE 可以完成此属性。
我子class编辑了真实的class
我在 class
中添加了伪 我用这个class而不是真正的作为参数类型提示
class Request(_Request): """ HTTP request class. This is a Pyramid Request object augmented with type hinting information for Websauna-specific functionality. To know more about request read also * py:class:`pyramid.request.Request` documentation * py:class:`webob.request.Request` documentation Counterintuitively, this request is also available in non-HTTP applications like command line applications and timed tasks. These applications do not get request URL from a front end HTTP webserver, but a faux request is constructed pointing to the website URL taken from ``websauna.site_url`` setting. This is to allow similar design patterns and methodology to be applied in HTTP and non-HTTP applications. By setting variables in ``__type_hinting__()`` based on arguments types allows IDEs to infer type information when you hint your views as:: from websauna.system.http import Request def hello_world(request: Request): request. # <-- When typing, here autocompletion kicks in. """ def __type_hinting__(self, user: Optional[User], dbsession: Session, session: ISession, admin: Admin, registry: Registry): """ A dummy helper function to tell IDEs about reify'ed variables. :param user: The logged in user. None if the visitor is anonymous. :param dbsession: Current active SQLAlchemy session :param session: Session data for anonymous and logged in users. :param admin: The default admin interface of the site. Note that the site can have several admin interfaces for different purposes. :param registry: Pyramid registry's. E.g. :py:attr:`pyramid.registry.Registry.settings` for reading settings and :py:meth:`pyramid.registry.Registry.notify` for sending events. """ self.user = user self.dbsession = dbsession self.session = session self.admin = admin self.registry = registry
__type_hinting__
方法
在 Python 3.6+ 中,您可以使用 class-level 类型提示 - 这些不会在 class 中生成属性。即
class Request(_Request):
user: Optional[User]
这不会在 class 中创建属性,只会创建注释。
>>> 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]}
在 Python 3.5 中可以创建一个 returns 一个 non-data 描述符的函数(即 没有 __set__
);这将被实例属性覆盖,但它带有 一些最小的 运行时开销 - 将从 __dict__
获取描述符并检查它是否定义了 __set__
插槽- 即使是所有阅读。它可能看起来像
class Request(_Request):
user = typed(User)
其中 typed
定义为
def typed(type: Type[T]) -> T:
... return a dummy non-data-descriptor...
这应该足以 PyCharm 正确推断类型。