Rod*_*ins 9 python type-hinting code-completion
我刚刚为 Python编写了一个简单的@autowired装饰器,它根据类型注释实例化类。
为了启用类的延迟初始化,包提供了一个lazy(type_annotation: (Type, str))函数,以便调用者可以像这样使用它:
@autowired
def foo(bla, *, dep: lazy(MyClass)):
...
Run Code Online (Sandbox Code Playgroud)
这工作得很好,在幕后这个lazy函数只是返回一个函数,该函数返回实际类型并且将lazy_init属性设置为True。也这并没有打破的IDE(例如,PyCharm)代码完成功能。
Lazy类型 use 而不是lazy函数的使用。像这样:
@autowired
def foo(bla, *, dep: Lazy[MyClass]):
...
Run Code Online (Sandbox Code Playgroud)
这会表现得非常像Typing.Union。而当我能够实现标化的类型,Ides的代码完成功能将形同虚设,因为它会出现在为属性的建议Lazy类,而不是MyClass。
我一直在使用此代码:
class LazyMetaclass(type):
def __getitem__(lazy_type, type_annotation):
return lazy_type(type_annotation)
class Lazy(metaclass=LazyMetaclass):
def __init__(self, type_annotation):
self.type_annotation = type_annotation
Run Code Online (Sandbox Code Playgroud)
我尝试重新定义Lazy.__dict__为转发到下标类型的属性,__dict__但这似乎对 PyCharm 的代码完成功能没有影响。
我坚信我想要实现的目标是可能的,因为Typing.Union可以很好地与 IDE 的代码完成配合使用。我一直试图破译typing.Union的源代码中的内容,使其在代码完成功能方面表现良好,但到目前为止还没有成功。
Mar*_*ers 10
为了使Container[Type]表示法起作用,您需要创建一个用户定义的泛型类型:
from typing import TypeVar, Generic
T = TypeVar('T')
class Lazy(Generic[T]):
pass
Run Code Online (Sandbox Code Playgroud)
然后你使用
def foo(bla, *, dep: Lazy[MyClass]):
Run Code Online (Sandbox Code Playgroud)
并且Lazy被视为一个容纳类的容器。
注意:这仍然意味着 IDE 将其dep视为类型的对象Lazy。Lazy这里是一个容器类型,持有一个类型的对象MyClass。您的 IDE 不会自动完成该MyClass类型,您不能那样使用它。
该符号也不会创建Lazy类的实例;它通过元类创建了一个子GenericMeta类。子类有一个特殊的属性,__args__可以让您内省订阅参数:
>>> a = Lazy[str]
>>> issubclass(a, Lazy)
True
>>> a.__args__
(<class 'str'>,)
Run Code Online (Sandbox Code Playgroud)
如果您只想在运行时访问类型注释但懒惰地解析名称,则可以只支持字符串值:
def foo(bla, *, dep: 'MyClass'):
Run Code Online (Sandbox Code Playgroud)
这是有效的类型注释,以及你的装饰器可以通过在运行时将名称解析typing.get_type_hints()功能(在延期的时间,而不是在装修时),或在你的包裹串lazy()在装修时可调用。
如果lazy()旨在将类型标记为与其他类型提示不同的处理方式,那么您正在尝试使用其他含义重载类型提示注释,并且类型提示根本不支持此类用例,并且使用 Lazy[...]包含不能让它起作用。
| 归档时间: |
|
| 查看次数: |
7771 次 |
| 最近记录: |