【问题标题】:Deriving from typing.Union with type arguments派生自类型参数的 typing.Union
【发布时间】:2021-07-03 13:36:17
【问题描述】:

我正在尝试从 typing.Union 派生一个类,并使用类型参数进行参数化,但我收到了一个我不理解的 TypeError。

这些都可以正常工作:

import typing

class Foo(typing.Dict[str, int]): pass
class Bar(typing.Union[str]): pass
typing.Union[str, int]

(当然,Union[str] 是多余的,可能只是str。)

但以下引发TypeError: __init__() takes 2 positional arguments but 4 were given

class Foo(typing.Union[str, int]): pass

class Foo(typing.Optional[str]) 引发相同的错误,这是有道理的,因为 typing.Optional[str] 等同于 typing.Union[NoneType, str]

另一方面,如果出于某种原因应该避免子类化Union 而子类化DictList 很好(我在this portion of the Mypy docs 之后模糊地建模我的代码),我想知道它是什么。

【问题讨论】:

    标签: python python-typing


    【解决方案1】:

    According to the docs,您不能继承或实例化联合。

    class Foo(typing.Union[str, int]):
        pass
    
    def f(foo: Foo):
        print(foo)
        
    f(1)
    

    加注

    Traceback (most recent call last):
      File "<string>", line 3, in <module>
    File "/usr/lib/python3.8/typing.py", line 317, in __new__
        raise TypeError(f"Cannot subclass {cls!r}")
    TypeError: Cannot subclass <class 'typing._SpecialForm'>
    

    相反,您可以创建一个类型别名:

    Foo = typing.Union[str, int]
    
    def f(foo: Foo):
        print(foo)
        
    f(1)
    

    按预期工作。


    你可能会问为什么

    class Bar(typing.Union[str]):
        pass
    

    有效。如果您在创建 typing.Union 时查看 at the source code (__new__),您会看到这个 sn-p:

    if origin is Union:
        parameters = _remove_dups_flatten(parameters)
        # It's not a union if there's only one type left.
        if len(parameters) == 1:
            return parameters[0]
    

    这意味着,如果一个typing.Union 有一个类型,它将等价于这个类型。事实上,

    print(isinstance(Bar(), str))
    

    输出为真。

    【讨论】:

    • 看来 Python 的行为已从 3.8 更改为 3.9(我正在运行)。在 3.8 中,我也收到了您报告的异常,但在 3.9 中,我收到了(不太有用的)TypeError: __init__() takes 2 positional arguments but 4 were given
    猜你喜欢
    • 1970-01-01
    • 2013-09-11
    • 2011-10-09
    • 2011-03-20
    • 2016-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    相关资源
    最近更新 更多