检查 stdlib 函数时出现 Mypy 错误?

Posted

技术标签:

【中文标题】检查 stdlib 函数时出现 Mypy 错误?【英文标题】:Mypy error when checking stdlib functions? 【发布时间】:2021-06-26 13:48:25 【问题描述】:

我有一个例程来创建一个有效的 powerset。我为参数和返回值添加了一些类型注释,然后在结果上运行 Mypy。

Mypy 似乎与 stdlib 函数有问题,这是意料之中的吗?

(base) paddy3118@Paddy-G14:/mnt/c/Users/paddy/Google Drive/Code$ python -V
Python 3.8.5
(base) paddy3118@Paddy-G14:/mnt/c/Users/paddy/Google Drive/Code$ mypy -V
mypy 0.761
(base) paddy3118@Paddy-G14:/mnt/c/Users/paddy/Google Drive/Code$ uname -a
Linux Paddy-G14 4.19.128-microsoft-standard #1 SMP Tue Jun 23 12:58:10 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
(base) paddy3118@Paddy-G14:/mnt/c/Users/paddy/Google Drive/Code$ cat pwrset_mypy.py
# -*- coding: utf-8 -*-
"""
Created on Tue Mar 30 14:59:19 2021

@author: Paddy3118
"""
from itertools import chain, combinations
from typing import List, Tuple


def powerset(s: List[int]) -> List[Tuple[int]]:
    """powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3) ."""
    return list(chain.from_iterable(combinations(s, r) for r in range(len(s)+1)))

if __name__ == '__main__':
    assert powerset([0, 1, 2]) == [(), (0,), (1,), (2,), (0, 1), (0, 2),
                                   (1, 2), (0, 1, 2)]
(base) paddy3118@Paddy-G14:/mnt/c/Users/paddy/Google Drive/Code$
(base) paddy3118@Paddy-G14:/mnt/c/Users/paddy/Google Drive/Code$ mypy  --show-error-context --show-column-numbers --show-error-codes --pretty pwrset_mypy.py
pwrset_mypy.py: note: In function "powerset":
pwrset_mypy.py:13:37: error: Generator has incompatible item type "Iterator[Tuple[int, ...]]"; expected
"Iterable[Tuple[int]]"  [misc]
        return list(chain.from_iterable(combinations(s, r) for r in range(len(s)+1)))
                                        ^
Found 1 error in 1 file (checked 1 source file)
(base) paddy3118@Paddy-G14:/mnt/c/Users/paddy/Google Drive/Code$
``

【问题讨论】:

Tuple[int] 表示包含 single int 的元组。 如何说明它返回零个或多个整数的元组列表? 就在你从mypy得到的错误信息中... 【参考方案1】:

您收到错误是因为您的类型注释错误。错误消息准确地告诉您如何修复它 - 您可以使用 Tuple[int, ...] 而不是 Tuple[int]

def powerset(s: List[int]) -> List[Tuple[int, ...]]:
    """powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3) ."""
    return list(chain.from_iterable(combinations(s, r) for r in range(len(s)+1)))

除非调用者知道这些是特定的元组很重要,否则另一种选择是将它们指定为Iterable[int]s:

def powerset(s: List[int]) -> List[Iterable[int]]:
    """powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3) ."""
    return list(chain.from_iterable(combinations(s, r) for r in range(len(s)+1)))

请注意,Tuple[int] 是一个包含单个 int 的元组,而 Iterable[int] 是包含任意数量的 ints 的任何可迭代对象。元组类型声明为元组的每个位置采用一个类型参数——因为每个单独的元组都是不可变的,所以可以注释每个位置并知道类型将被保留,因此您可以使用例如 Tuple[int, int] 或 @ 987654331@等

【讨论】:

成功!谢谢 - 我被错误的给定位置抛出。 我认为它指向那个位置,因为那是与您的返回类型不一致的值的来源。 chain.from_iterable 只返回其输入的类型,因此将其作为错误的来源是没有帮助的。与您声明的Tuple[int] 返回类型不一致的Tuple[int, ...] 返回类型实际上来自combinations 谢谢。希望我对 Mypy 错误的理解会随着使用而增长。 mypy 大约四年前第一次开始使用它时让我很恼火和困惑,现在它确实是我最喜欢使用 Python 的部分:D

以上是关于检查 stdlib 函数时出现 Mypy 错误?的主要内容,如果未能解决你的问题,请参考以下文章

将值列表映射到浮点数时出现mypy错误

从 C 调用汇编函数时出现分段错误错误

在 Rust 项目的 C 绑定上运行 jextract 时出现致命错误“'stdlib.h' 文件未找到”

scanf 调用时出现“无法打开输出文件”错误

在C中调用fgets时出现分段错误

使用 mypy 进行类型检查,我无法弄清楚为啥会发生此错误 [关闭]