我将为几种类型的组合创建一个“类型别名”。我可以为大多数类型创建一个新类,但这会使代码太长并且类型检查器无法显示它。我正在寻找更好的替代方案。我们可以使用
Union
来代替 A | B
,但我需要 A & B
。
示例:
from typing import TypeVar
T = TypeVar('T')
class Identify:
id: int
def test_type_hints(obj: T) -> T & Identify: # This Line
obj.id = id(obj)
如果我能做到,怎么做?否则为什么?
您显示的代码实际上并未将
obj
转换为 Identify
的实例,因此您要求添加的类型提示会产生误导。在运行时调用 isinstance(obj, Identify)
将是 false,并且没有类型检查声明会接受该对象作为类的实例。
如果您希望
Identify
类型不是期望您子类化并创建其实例的真实类型,而只是“具有 id
属性的对象”的能指,那么您应该将其设为 typing.Protocol
。协议正是您想要的,它可以让您描述对象必须具有的功能,并且任何类型的任何此类对象都将在期望对象遵守协议的任何地方被接受。
from typing import Protocol
class Identify(typing.Protocol):
id: int
class MyObj:
pass
o = MyObj()
print(isinstance(o, Identify)) # prints False
o.id = 2
print(isinstance(o, Identify)) # prints True now
这并不能完全解决你的问题,因为Python类型提示中并没有真正的机制来动态声明类型的交集(它一直是很长一段时间以来所要求的功能)。在某些情况下可能有效的一种粗略方法是丢弃旧类型信息并仅保留协议的新知识,但这对于您的用例来说可能不够好:
def test_type_hints(obj: typing.Any) -> Identify:
obj.id = id(obj)
return obj