【问题标题】:mypy does not recognize assert and shows an errormypy 无法识别断言并显示错误
【发布时间】:2022-01-03 02:16:48
【问题描述】:

考虑x.py中的以下代码

from typing import Dict, List, Union


def _func2(do_something: bool) -> Dict[str, Dict[str, Union[str, List[str]]]]:
    dict1: Dict[str, Union[str, List[str]]] = dict()
    dict2: Dict[str, Union[str, List[str]]] = dict()
    dict3: Dict[str, Union[str, List[str]]] = dict()
    if (do_something):
        dict1['key1'] = 'string1'
        if ('key1' not in dict2.keys()):
            dict2['key1'] = list()
        assert(isinstance(dict2['key1'], list))
        dict2['key1'].append('otherstring')
    return {'outer_key_1': dict1, 'outer_key_2': dict2, 'outer_key_3': dict3}


def _func1(do_something: bool) -> Dict[str, Dict[str, Union[str, List[str]]]]:
    dict1: Dict[str, Union[str, List[str]]] = dict()
    dict2: Dict[str, Union[str, List[str]]] = dict()
    dict3: Dict[str, Union[str, List[str]]] = dict()
    keys: List[str] = ['key1']
    if (do_something):
        dict1['key1'] = 'string1'
        if (keys[0] not in dict2.keys()):
            dict2[keys[0]] = list()
        assert(isinstance(dict2[keys[0]], list))
        dict2[keys[0]].append('otherstring')
    return {'outer_key_1': dict1, 'outer_key_2': dict2, 'outer_key_3': dict3}

命令mypy --strict --show-error-codes x.py显示

x.py:27: error: Item "str" of "Union[str, List[str]]" has no attribute "append"  [union-attr]
Found 1 error in 1 file (checked 1 source file)

注意:_func2 和 _func1 的唯一区别是,_func1 中的键是字符串列表的一部分,而不是直接的字符串。

代码在运行时是可运行的——当然,如果函数被调用——但如果我需要使用 _func1(代码示例中的列表是静态的,在现实生活中不是),我如何满足 mypy?

【问题讨论】:

  • 你可以通过设置x = dict[keys[0]]; assert isinstance(x, list); x.append(...) 来解决这个问题——虽然它很笨重,所以我将它作为评论留下,希望有人能用更惯用/优雅的东西来回答。
  • 你能把这段代码删减一点吗?即使看了一会儿,我也不确定哪些部分是相关的,以及 MyPy(据说)在哪里旅行。我是否正确地认为更改归结为使用 literal 'key1'dynamic keys[0]?这三个 dicts 是否相关,或者一个就足够了?
  • 嗨@MisterMiyagi,你读过我的“笔记”吗?我认为这很好地解释了它,不是吗?如果您将代码复制到 python 文件并使用我包含的命令运行 mypy,您会看到第 27 行在哪里......我真的不明白如何让这更容易理解,抱歉。
  • 您绝对可以删除dict1dict3do_somethingif (... not in dict2.keys()): 似乎也是多余的——你可以直接将dict2 初始化为{'key1': []}。您还可以删除所有布尔检查的非惯用括号,尽管在上次清理后只有 assert 会保留。 That cuts the function size easily in half.

标签: python-3.x mypy


【解决方案1】:

我还为mypy开了一张票:https://github.com/python/mypy/issues/11732
该票已关闭,并附有指向 https://github.com/python/mypy/issues/11534 的链接,该链接解释说这将不会实施 - 作为解决方案,提供了一个示例,如评论中超中微子提到的。

【讨论】:

  • 您能否在答案中包含相关信息?从问题中很难知道“this”是什么,并且链接问题和未链接评论中的解决方案将来可能无法获得。
  • "下标表达式为动态时不支持下标表达式的类型窄化,下标表达式为字符串或数值文字值时支持。动态下标表达式的类型窄化很难实现,因为它要求类型检查器确保在类型保护测试中找到的表达式的值与在保护块中找到的表达式的值相同”来自https://github.com/python/mypy/issues/11534
猜你喜欢
  • 2020-08-02
  • 2013-03-12
  • 2021-10-22
  • 2018-03-21
  • 2021-03-22
  • 2020-08-23
  • 2022-12-22
  • 2021-02-14
  • 2020-05-16
相关资源
最近更新 更多