1

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

但是,当使用类型提示 + 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 中的错误吗?

4

1 回答 1

1

似乎这里的问题是 attrgetter 有 return type Any,而 mypy 没有抓住这一点。

我将此发布到 mypy repo 并得到以下答案

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

于 2017-02-21T09:54:05.897 回答