Python 有趣的MYPY行为-仅对difflib发出一次警告

Python 有趣的MYPY行为-仅对difflib发出一次警告,python,mypy,Python,Mypy,我有以下代码: """ FILE: diff_tool.py VERSION: .1 - initial file with arguments .2 - adding HTML output DESCRIPTION: script that shows the difference between two files. https://florian-dahlitz.de/blog/create-your-own-diff-tool-using-p

我有以下代码:

"""
FILE:
    diff_tool.py

VERSION:
    .1 - initial file with arguments
    .2 - adding HTML output

DESCRIPTION:
    script that shows the difference between two files.

    https://florian-dahlitz.de/blog/create-your-own-diff-tool-using-python
"""

import difflib
import sys
import argparse

from pathlib import Path
from typing import Union, Iterator

def create_diff(old_file: Path, new_file: Path, output_file: Path=None) -> None:
    file_1 = open(old_file).readlines()
    file_2 = open(new_file).readlines()

    old_name: str = old_file.name
    new_name: str = new_file.name
    delta: Union[str, Iterator[str]] = ""
    if output_file:
        delta = difflib.HtmlDiff().make_file(
            file_1, file_2, old_name, new_name
        )
        with open(output_file, "w") as f:
            f.write(delta)
            f.close()
    else:
        delta = difflib.unified_diff(file_1, file_2, old_name, new_name)
        sys.stdout.writelines(delta)


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("old_file_version")
    parser.add_argument("new_file_version")
    parser.add_argument("--html", help="specify html to write to")
    args = parser.parse_args()

    old_file = Path(args.old_file_version)
    new_file = Path(args.new_file_version)

    if args.html:
        output_file = Path(args.html)
    else:
        output_file = None

    create_diff(old_file, new_file, output_file)


if __name__ == "__main__":
    main()
我在else语句之后评论了mypy警告,它是:

Incompatible types in assignment (expression has type "Iterator[str]", variable has type "str")
问题是错误不会出现两次。我知道这与file1和file2中的readlines有关,但是为什么在将diff工作写入HTML文件时不会发生这种情况呢

更新:
我已经更新了代码,但多亏了Samwise定义了delta,也解决了这个问题,一切正常,没有mypy错误。我肯定要开始真正深入研究键入。

第一次为变量赋值时,在本例中,如果不提供类型注释,则会根据赋值推断类型。如果分配不兼容的类型,后续分配将产生错误

因此,第一个赋值不会出错,因为它与任何内容都不冲突;第二个赋值错误,因为它与第一个赋值冲突

由于这个值不在这些块之外使用,我建议只使用两个不同的变量名,因为您有两种不同类型的值。即:

if output_file:
    delta_as_str = difflib.HtmlDiff().make_file(
        file_1, file_2, old_name, new_name
    )
    with open(output_file, "w") as f:
        f.write(delta_as_str)
        f.close()
else:
    delta_as_iter = difflib.unified_diff(file_1, file_2, old_name, new_name)
    sys.stdout.writelines(delta_as_iter)
如果您确实需要一个变量来潜在地包含不同类型的值,那么修复方法是在初始化时将其声明为联合类型,以便让mypy知道,即使您现在给它一个str值,它以后也可以使用迭代器[str]值:

    delta: Union[str, Iterator[str]] = difflib.HtmlDiff().make_file(
        file_1, file_2, old_name, new_name
    )

当然,这意味着您在该点之后对值所做的一切都必须考虑到这两种类型!一般来说,每个变量只有一个类型更好,这样您就不必做大量的if-isinstance。。。稍后再检查。

第二个错误发生在哪里?我真的没想到会发生任何错误。它运行时没有问题,只是mypy有问题。现在我不能在定义delta的if语句中写入deltaIO写入的参数1具有不兼容的类型Union[str,迭代器[str]];期待str``我会看看这个,但谢谢我知道我必须定义delta的类型。就像我说的,使用两个不同的变量,而不是尝试执行Union:Edited ANSWERT,以明确显示如何执行此操作。我使用您对增量的声明使其工作。我只是在输入if语句之前执行了此操作,没有更多错误。您可以使其工作,但这确实是不必要的痛苦,而且在我看来,让变量的范围比它需要的范围更广是一种不好的做法。就我个人而言,我甚至不会让它成为一个命名变量同意最终版本我这么做完全是因为我在想同样的事情。