可选[Type [Foo]]在Python 3.5.2中引发TypeError

Mar*_*ham 6 python annotations typing python-3.x python-3.5

这段代码:

#!/usr/bin/env python

from typing import Optional, Type

class Foo(object):
    pass

class Bar(Foo):
    pass

def test_me() -> Optional[Type[Foo]]:
    print("Hi there!")
    return Bar

if __name__ == "__main__":
    test_me()
Run Code Online (Sandbox Code Playgroud)

TypeError在3.5.2 加注:

Traceback (most recent call last):
  File "./test.py", line 11, in <module>
    def test_me() -> Optional[Type[Foo]]:
  File "/Users/mnot/.pyenv/versions/3.5.2/lib/python3.5/typing.py", line 649, in __getitem__
return Union[arg, type(None)]
  File "/Users/mnot/.pyenv/versions/3.5.2/lib/python3.5/typing.py", line 552, in __getitem__
dict(self.__dict__), parameters, _root=True)
  File "/Users/mnot/.pyenv/versions/3.5.2/lib/python3.5/typing.py", line 512, in __new__
for t2 in all_params - {t1} if not isinstance(t2, TypeVar)):
  File "/Users/mnot/.pyenv/versions/3.5.2/lib/python3.5/typing.py", line 512, in <genexpr>
for t2 in all_params - {t1} if not isinstance(t2, TypeVar)):
  File "/Users/mnot/.pyenv/versions/3.5.2/lib/python3.5/typing.py", line 1077, in __subclasscheck__
if super().__subclasscheck__(cls):
  File "/Users/mnot/.pyenv/versions/3.5.2/lib/python3.5/abc.py", line 225, in __subclasscheck__
for scls in cls.__subclasses__():
TypeError: descriptor '__subclasses__' of 'type' object needs an argument
Run Code Online (Sandbox Code Playgroud)

而它在3.6上运行良好.如果我拼出可选的同样的问题Union[None, Type[Foo]].

是否有3.5.2的解决方法,同时仍然准确地注释返回类型?

Zer*_*eus 5

这是Python 3.5.2中的错误

Optional[cls]为包装器Union[cls, type(None)],其使用__subclasses__()来建立一类是否是另一个的子类。

但是,TypetypePython 3.5.2 的子类,这意味着

Union[Type[anything], anything_else]
Run Code Online (Sandbox Code Playgroud)

最终会打电话

type.__subclasses__()
Run Code Online (Sandbox Code Playgroud)

…这是一个问题,因为它type是一个元类,因此希望与正在寻找其子类的类一起调用,其方式与在常规类上调用实例方法需要您提供其自身的实例的方式完全相同str.upper('foo')

通过不再将其作为的子类,此问题已在Python 3.5.3(以及您已经注意到的3.6)中得以解决Typetype