定义一个行为类似于 typing.Any 的自定义类型
Define a custom Type that behaves like typing.Any
我需要创建一个类型,当类型检查器 (mypy) 查看时,它的行为类似于 typing.Any
,但与 typing.Any
不同。
用例是一些漂亮的 "meta" 代码,需要从一组可以用 typing.Any
注释的其他变量中找到用这种类型注释的变量。
请注意,我永远不必实际创建此类型的实例,我只需要它用于数据类上下文中的类型注释。
示例:
from dataclasses import dataclass, fields
from typing import Any
MyAny = ... # What to put here?
@dataclass()
class Test:
a: Any
b: MyAny = None
for field in fields(Test):
if field.type == MyAny:
print(f"It's {field.name}") # This should print "It's b"
我尝试过的事情:
不起作用,因为您不能继承 Any:TypeError: Cannot subclass <class 'typing._SpecialForm'>
class MyAny(Any):
pass
不起作用,因为它无法与普通的 Any 区分开来(上面截取的代码的结果是 It's a\nIt's b
)
MyAny = Any
在运行时工作,但 mypy 抱怨默认值:
Mypy: Incompatible types in assignment (expression has type "None", variable has type "MyAny")
class MyAny:
pass
在运行时工作,但 mypy 无法判断这应该表现得像 Any
:
它抱怨的定义是
Mypy: Argument 2 to NewType(...) must be subclassable(got "Any")
它抱怨默认参数:
Mypy: Incompatible types in assignment (expression has type "None", variable has type "MyAny")
from typing import NewType
MyAny = NewType("MyAny", Any)
那么有什么办法可以做到这一点吗?
您可以使用 TypeVar。
# foo.py
from dataclasses import dataclass, fields
from typing import Any, TypeVar, Generic, Optional
MyAny = TypeVar('MyAny')
@dataclass()
class Test(Generic[MyAny]):
a: Any
b: Optional[MyAny] = None
for field in fields(Test):
if field.type == Optional[MyAny]:
print(f"It's {field.name}")
输出
$ python3 foo.py
It's b
$ mypy foo.py
Success: no issues found in 1 source file
您可以使用条件来欺骗 mypy 解释一段代码,同时让您的运行时执行另一段代码。
from dataclasses import dataclass, fields
from typing import Any
if False:
MyAny = Any
else:
class MyAny: # type: ignore
pass
@dataclass()
class Test:
a: Any
b: MyAny = None
for field in fields(Test):
if field.type == MyAny:
print(f"It's {field.name}") # This should print "It's b"
我需要创建一个类型,当类型检查器 (mypy) 查看时,它的行为类似于 typing.Any
,但与 typing.Any
不同。
用例是一些漂亮的 "meta" 代码,需要从一组可以用 typing.Any
注释的其他变量中找到用这种类型注释的变量。
请注意,我永远不必实际创建此类型的实例,我只需要它用于数据类上下文中的类型注释。
示例:
from dataclasses import dataclass, fields
from typing import Any
MyAny = ... # What to put here?
@dataclass()
class Test:
a: Any
b: MyAny = None
for field in fields(Test):
if field.type == MyAny:
print(f"It's {field.name}") # This should print "It's b"
我尝试过的事情:
不起作用,因为您不能继承 Any:
TypeError: Cannot subclass <class 'typing._SpecialForm'>
class MyAny(Any): pass
不起作用,因为它无法与普通的 Any 区分开来(上面截取的代码的结果是
It's a\nIt's b
)MyAny = Any
在运行时工作,但 mypy 抱怨默认值:
Mypy: Incompatible types in assignment (expression has type "None", variable has type "MyAny")
class MyAny: pass
在运行时工作,但 mypy 无法判断这应该表现得像
Any
: 它抱怨的定义是Mypy: Argument 2 to NewType(...) must be subclassable(got "Any")
它抱怨默认参数:Mypy: Incompatible types in assignment (expression has type "None", variable has type "MyAny")
from typing import NewType MyAny = NewType("MyAny", Any)
那么有什么办法可以做到这一点吗?
您可以使用 TypeVar。
# foo.py
from dataclasses import dataclass, fields
from typing import Any, TypeVar, Generic, Optional
MyAny = TypeVar('MyAny')
@dataclass()
class Test(Generic[MyAny]):
a: Any
b: Optional[MyAny] = None
for field in fields(Test):
if field.type == Optional[MyAny]:
print(f"It's {field.name}")
输出
$ python3 foo.py
It's b
$ mypy foo.py
Success: no issues found in 1 source file
您可以使用条件来欺骗 mypy 解释一段代码,同时让您的运行时执行另一段代码。
from dataclasses import dataclass, fields
from typing import Any
if False:
MyAny = Any
else:
class MyAny: # type: ignore
pass
@dataclass()
class Test:
a: Any
b: MyAny = None
for field in fields(Test):
if field.type == MyAny:
print(f"It's {field.name}") # This should print "It's b"