子类的 Python 打字问题

Agh*_*ese 4 python mypy python-typing

这个问题是为了澄清我对 python 打字的疑问

from typing import Union

class ParentClass:
    parent_prop = 1

class ChildA(ParentClass):
    child_a_prop = 2

class ChildB(ParentClass):
    child_b_prop = 3

def method_body(val) -> ParentClass:
    if val:
        return ChildA()
    else:
        return ChildB()

def another_method() -> ChildA:
    return method_body(True)

print(another_method().child_a_prop)
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,我使用的 linting 工具打印错误如下

error: Incompatible return value type (got "ParentClass", expected "ChildA")
Run Code Online (Sandbox Code Playgroud)

(我在哪里做method_body(True)

我还将method_body返回类型设置为 Union[ChildA, ChildB]. 这将导致error: Incompatible return value type (got "Union[ChildA, ChildB]", expected "ChildA")

我正在寻找更好的方法来做到这一点。如果有人知道解决方案,我们将非常感谢您的帮助。

qou*_*ify 5

mypy 不进行运行时分析,因此它无法猜测 method_body带参数的调用True将始终生成ChildA对象。所以它产生的错误确实是有道理的。

您必须以某种方式引导 mypy 告诉他您知道自己在做什么,并且在使用 argument 调用时another_method确实会产生一个对象。一种是使用:ChildATruecast

from typing import cast
def another_method() -> ChildA:
    return cast(ChildA, method_body(True))
Run Code Online (Sandbox Code Playgroud)

另一种是添加断言:

def another_method() -> ChildA:
    result = method_body(True)
    assert isinstance(result, ChildA)
    return result
Run Code Online (Sandbox Code Playgroud)

两者之间的区别在于cast没有任何运行时含义。您可以将其视为放在这里的注释,以指导 mypy 进行检查,但该cast函数仅返回其第二个参数,即,这里是主体cast

def cast(typ, val):
    return val
Run Code Online (Sandbox Code Playgroud)

assert自然会引发AssertionError错误(在这种情况下显然不是这样,但一般情况下)。