Python中的受限泛型类型提示
我想创建一个类似于这里的工厂方法Python中的受限泛型类型提示,python,type-hinting,typing,Python,Type Hinting,Typing,我想创建一个类似于这里的工厂方法 class A: ... class B(A): def f(self): ... class C: ... def factory(cls): return cls() 但我想添加一些类型提示,其中包含两个要求: 只有A的子类才允许作为factory的参数 当传递B时,会正确检测到factory(B)是B的实例,即factory(B).f()是允许的,而factory(A).f()不是 尝试1 使用键
class A:
...
class B(A):
def f(self):
...
class C:
...
def factory(cls):
return cls()
但我想添加一些类型提示,其中包含两个要求:
- 只有
的子类才允许作为A
的参数factory
- 当传递
时,会正确检测到B
是factory(B)
的实例,即B
是允许的,而factory(B).f()
不是factory(A).f()
键入模块中的键入
from typing import Type
class A:
...
class B(A):
def f(self):
...
class C:
...
def factory(cls: Type[A]):
return cls()
factory(A) # Ok
factory(B) # Ok
factory(C) # Fail
factory(A).f() # Fail
factory(B).f() # Fail -- Wrong!
这个函数正确地检测到C
不应该作为factory
的参数传递。但是,类型检查器不允许使用工厂(B).f()
尝试2
使用TypeVar
from typing import TypeVar, Type
T = TypeVar('T')
class A:
...
class B(A):
def f(self):
...
class C:
...
def factory(cls: Type[T]) -> T:
return cls()
factory(A) # Ok
factory(B) # Ok
factory(C) # Ok -- Wrong!
factory(A).f() # Fail
factory(B).f() # Ok
可以很好地推断,factory(B).f()
是好的,而factory(A).f()
不是。然而,泛型是没有限制的,即工厂(C)也是可以的
尝试3
将约束添加到T
from typing import TypeVar, Type
class A:
...
class B(A):
def f(self):
...
class D(A):
...
class C:
...
T = TypeVar('T', A)
def factory(cls: Type[T]) -> T:
return cls()
factory(A) # Ok
factory(B) # Ok
factory(C) # Fail
factory(A).f() # Fail
factory(B).f() # Ok
这看起来很有希望,至少PyCharm能够正确处理所有情况。但是对于实际应用来说,这个解决方案实际上是最糟糕的-不允许单个约束
出现错误,尽管还不清楚原因。在PEP 484中,只有一句简短的话说“应该至少有两个约束条件,如果有的话;不允许指定单个约束。”
有什么好的解决办法吗?我只想添加一个'dummy'类\u a
,一个a
的空白子类,并将其作为另一个约束条件来使用类似的内容
_A = NewType('_A', A)
T = TypeVar('T', A, _A)
def factory(cls: Type[T]) -> T:
return cls()
但是我并不认为这是一个好的解决方案。
提前谢谢你 将
类型变量
与绑定
一起使用似乎有效:
from typing import Type, TypeVar
class A:
...
class B(A):
def f(self):
...
class C:
...
AnyA = TypeVar("AnyA", bound=A)
def factory(cls: Type[AnyA]) -> AnyA:
return cls()
factory(A).f() # error: "A" has no attribute "f"
factory(B).f() # ok!
factory(C) # error: Value of type variable "AnyA" of "factory" cannot be "C"
将
TypeVar
与绑定一起使用似乎可以:
from typing import Type, TypeVar
class A:
...
class B(A):
def f(self):
...
class C:
...
AnyA = TypeVar("AnyA", bound=A)
def factory(cls: Type[AnyA]) -> AnyA:
return cls()
factory(A).f() # error: "A" has no attribute "f"
factory(B).f() # ok!
factory(C) # error: Value of type variable "AnyA" of "factory" cannot be "C"
说:
…类型变量可以使用bound=
指定上限。这意味着被类型变量替换(显式或隐式)的实际类型必须是边界类型的子类
这看起来和你想要的一模一样,所以你可以写:
T = TypeVar('T', bound=A)
说:
…类型变量可以使用bound=
指定上限。这意味着被类型变量替换(显式或隐式)的实际类型必须是边界类型的子类
这看起来和你想要的一模一样,所以你可以写:
T = TypeVar('T', bound=A)
哦,当然。。我完全想念它。非常感谢。哦,当然。。我完全想念它。非常感谢。