定义一个行为类似于打字的自定义类型。Any

Run*_*ith 3 python types type-hinting mypy python-dataclasses

我需要创建一个类型,其行为类似于typing.Any类型检查器(mypy)查看时的行为,但与typing.Any.

用例是一些漂亮的“元”代码,需要从一组可以用 注释的其他变量中找到用此类型注释的变量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"
Run Code Online (Sandbox Code Playgroud)

我尝试过的事情:

  1. 不起作用,因为你不能继承 Any:TypeError: Cannot subclass <class 'typing._SpecialForm'>

    class MyAny(Any):
       pass
    
    Run Code Online (Sandbox Code Playgroud)
  2. 不起作用,因为它与正常的 Any 没有区别(上面代码片段的结果是It's a\nIt's b

    MyAny = Any
    
    Run Code Online (Sandbox Code Playgroud)
  3. 在运行时工作,但 mypy 抱怨默认值: Mypy: Incompatible types in assignment (expression has type "None", variable has type "MyAny")

    class MyAny:
       pass
    
    Run Code Online (Sandbox Code Playgroud)
  4. 在运行时工作,但 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)
    
    Run Code Online (Sandbox Code Playgroud)

那么有没有办法让这项工作发挥作用呢?

Mar*_*zer 5

您可以使用条件来欺骗 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"
Run Code Online (Sandbox Code Playgroud)