MyPy / python类型提示不会捕获可以返回多种类型的被调用函数

时间:2017-02-20 17:40:27

标签: python python-3.x type-hinting mypy

attrgetter函数可以根据您提供的参数返回不同的类型。如果你传递一个带有一个项目的iterable,它将只返回一个对象的给定字段;如果你传递一个包含多个项目的iterable,它会返回一个对象的这些字段的元组。

然而,当使用类型提示+ MyPy时,MyPy不会拾取这种差异(它不会引发任何错误):

from operator import attrgetter


class OneThing:
    foobar = "hello"
    fields = ['foobar']


class TwoThings:
    foobar = "hello"
    goodbye = "potatoes"
    fields = ['foobar', 'goodbye']


def attrgettertest(thing) -> tuple:
    return attrgetter(*thing.fields)(thing)


def main():
    onething = OneThing()
    twothings = TwoThings()

    t1 = attrgettertest(onething)
    t2 = attrgettertest(twothings)

    print("Attrgettertest on 'onething' returned  {} with type {}".format(
        t1, type(t1)))
    print("Attrgettertest on 'twothings' returned  {} with type {}".format(
        t2, type(t2)))


if __name__ == "__main__":
    main()

输出:

$ python attrgettrtest.py 
Attrgettertest on 'onething' returned  hello with type <class 'str'>
Attrgettertest on 'twothings' returned  ('hello', 'potatoes') with type <class 'tuple'>
$ mypy attrgettrtest.py 
$ 

预期结果将是这样的:

import random    

def test() -> tuple:
    if random.choice([0, 1]):
        return ("foo", "bar")
    return "foo"

if __name__ == "__main__":
    for n in range(20):
        print(test())

$ mypy test.py 
test.py:8: error: Incompatible return value type (got "str", expected Tuple[Any, ...])

这是MyPy中的错误吗?

1 个答案:

答案 0 :(得分:0)

这里的问题似乎是attrgetter的返回类型为Any,mypy没有捕捉到它。

我将其发布到mypy repo并获得以下answer

  

我认为问题在于attrgetter的返回类型为Any,因此您的代码会通过。原则上,在这种情况下难以进行精确的类型检查,但是,新添加的标志--warn-return-any将在这种情况下发出警告(将在0.480中提供,有关详细信息,请参阅PR #2854 )。