【问题标题】:type annotation with inheritance in python [duplicate]在python中具有继承的类型注释[重复]
【发布时间】:2020-03-23 12:29:54
【问题描述】:

我正在尝试为使用特定基类的子类的类 init 方法提供类型提示。 Gooling 如何做到这一点告诉我使用 Type[BaseClass] 作为注释,但是检查一直告诉我我错了。

作为我的问题的一个例子,假设这是base.py

class B:
    def __init__(self):
        return

..还有另一个class.py...

class SomeClass:

    def __init__(self, some_param: Type[B]):
        self.sp = some_param

现在,在第三个文件test.py 中以下列方式使用这些类给我带来了一些困惑:

from base import B
from class import SomeClass 

if __name__ == '__main__':
    sc = SomeClass(B())

我会猜到这是正确的,但 pycharm 检查用提示强调它:

预期类型“Type[B]”,改为“B”

所以由于这不起作用,我想我可能需要使用TypeVar,所以我将base.py 更改为:

class B:
    def __init__(self):
        return

TB = TypeVar('TB', bound=B)

class.py 到:

class SomeClass:

    def __init__(self, some_param: Type[TB]):
        self.sp = some_param

但是,这只是将 pycharm 检查更改为:

预期类型“Type[TB]”,改为“B”

最后,如果我将class.py 设置为:

class SomeClass:

    TB = TypeVar('TB', bound=B)

    def __init__(self, some_param: Type[TB]):
        self.sp = some_param

test.py中的检查错误消失了,pycharm没有投诉!

(奇怪的是,如果我将if __name__ == '__main__': sc = SomeClass(B()) 移动到class.py,仍然会有投诉。)

正如我所说,我对如何在 Python 中真正使用基类打字感到有点困惑:

  • 这一切都只是 pycharm 错误吗?

如果没有,

  • 为什么Type[B] 不够/有效?
  • 为什么需要在类中指定 TypeVar 而不能简单地导入 TypeVar

【问题讨论】:

  • 为什么不直接使用B 而不是Type[B]
  • def __init__(self, some_param: B) 不起作用?
  • Type[B]class B 的注解,而不是该类/类型的实例。您似乎将类误认为是它们的实例。您的类不使用“使用特定基类的子类”,它使用该特定基类的子类的 instances。正如其他人所指出的,您只需要 B 而不是 Type[B]
  • 是的,我想使用基类的实例或它的任何派生类,这就是为什么我认为我需要 Type[B] 根据 mypy 的文档:“有时你想谈论从给定类继承的类对象。这可以拼写为 Type[C] 其中 C 是一个类。换句话说,当 C 是一个类的名称时,使用 C 注释参数声明该参数是一个实例属于 C(或 C 的子类),但使用 Type[C] 作为参数注释声明参数是派生自 C(或 C 本身)的类对象。”我没有看到误解,我的错误是什么?
  • Type[B] 用于将B 本身(或B 的子类)作为参数传递。你想传递这样一个类的 instance,所以你想B 作为注解。 BType[B] 是两个完全不同的东西。

标签: python inheritance pycharm type-hinting base-class


【解决方案1】:

Type[B] 表示参数应该是一个类对象本身。

例如,

class A:
    pass

class B:
    pass

class C(B):
    pass

def foo(x: Type[B]):
    pass

foo(A)    # fails
foo(B)    # passes
foo(C)    # passes
foo(B())  # fails - an instance of B is not B or a subclass of B

您只需要B 作为类型提示,以允许B(或B 的子类)的实例作为参数。

class SomeClass:

    def __init__(self, some_param: B):
        self.sp = some_param

【讨论】:

  • 这正是问题所在。当他们谈论“类对象”时,我误解了 mypy 文档,没有看到它从字面上将类本身称为对象。我假设对象也意味着实例。非常感谢您的澄清。
猜你喜欢
  • 1970-01-01
  • 2015-10-01
  • 2013-08-31
  • 1970-01-01
  • 2014-01-26
  • 1970-01-01
  • 1970-01-01
  • 2014-11-15
  • 2015-02-11
相关资源
最近更新 更多