是否可以从 Python 中的 Generic 类继承?

8bi*_*oey 10 python generics inheritance descendant python-3.5

从 Python 3.5 开始,您可以使用PEP-0484 中描述的泛型和其他有趣的东西。我试过了,这是我的代码:

from typing import TypeVar, Generic, Optional
...

_T = TypeVar('T')
_S = TypeVar('S')


class Pool(Generic[_S, _T]):
    def __init__(self) -> None:
        self.pool = dict()

    ... getters and setters here...
Run Code Online (Sandbox Code Playgroud)

这段代码完美地工作并完成了预期的工作。然后我决定扩展这个类来做一些额外的工作。我就是这样做的:

class PoolEx(Pool[_S, _T]):

    ARGUMENTS = []

    def __init__(self) -> None:
        print("self=", self, self.__class__.__bases__)
        super(PoolEx, self).__init__()
        self.arguments_pool = dict()

    ... other code here ...
Run Code Online (Sandbox Code Playgroud)

为了测试Pool我创建的类MyPool,它看起来像这样:

class MyPool(Pool[str, Hello]):
    pass
Run Code Online (Sandbox Code Playgroud)

然后我放了类似的东西mypool = MyPool(),效果很好。实施后PoolEx,我已更新MyPool为:

class MyPool(PoolEx[str, Hello]):
    ARGUMENTS = ['name', 'surname']
Run Code Online (Sandbox Code Playgroud)

并试图做同样的事情:mypool = MyPool()。不幸的是我得到了:

self= <__main__.MyPool object at 0x1068644e0> (__main__.PoolEx[str, __main__.Hello],)
Traceback (most recent call last):
  File "/usr/local/Cellar/python3/3.5.0/Frameworks/Python.framework/Versions/3.5/lib/python3.5/runpy.py", line 170, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/local/Cellar/python3/3.5.0/Frameworks/Python.framework/Versions/3.5/lib/python3.5/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/Users/8bitjoey/.../utils/pool.py", line 141, in <module>
    mypool = MyPool()
  File "/Users/8bitjoey/.../utils/pool.py", line 52, in __init__
    super(PoolEx, self).__init__()
TypeError: super(type, obj): obj must be an instance or subtype of type
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,我也把self.__class__.__bases日志放到了日志中。当我尝试测试isinstance(self, PoolEx)并与 类似时issubclass,我得到了 False。与super()验证相同。

是我的代码有问题还是这样的类不能有后代?如果我仍然想要 PoolEx,我必须使用组合而不是继承。

AQT*_*QTS 3

好吧,仅供记录,我刚刚在 Python 3.8.10 上运行了您的代码,并且没有任何错误。它运行得很完美。然后我从 Docker Hub 中提取了 docker 镜像 python:3.5.0 并再次运行它,然后我得到了与您完全相同的错误:

TypeError: super(type, obj): obj must be an instance or subtype of type
Run Code Online (Sandbox Code Playgroud)

因此,此类功能的首次实现似乎已经存在问题,这些功能已在最新版本中得到修复。

以下是我用于测试的文件,以防有人有兴趣重现任何类似的错误:

from typing import TypeVar, Generic, Optional

_T = TypeVar('T')
_S = TypeVar('S')

class Pool(Generic[_S, _T]):
    def __init__(self) -> None:
        self.pool = dict()

class PoolEx(Pool[_S, _T]):
    ARGUMENTS = []

    def __init__(self) -> None:
        print("self=", self, self.__class__.__bases__)
        super(PoolEx, self).__init__()
        self.arguments_pool = dict()

class MyPool(Pool[str, int]):
    pass

mypool = MyPool()

class MyPool(PoolEx[str, int]):
    ARGUMENTS = ['name', 'surname']

mypool2 = MyPool()
Run Code Online (Sandbox Code Playgroud)