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

问题描述 投票:0回答:1

我有以下代码:

"""
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有关,但是为什么在将差异工作写入HTML文件时为什么没有出现?

更新:我已经更新了代码,但是感谢Samwise定义了delta并解决了问题,并且一切正常,没有mypy错误。我肯定会真正开始研究打字。

python mypy
1个回答
1
投票
第一次分配变量(在这种情况下为delta),如果不提供类型注释,则根据分配的值推断类型。如果您分配了不兼容的类型,则后续的分配将产生错误。

因此,第一次分配不会出错,因为它不会与任何内容冲突;第二个分配错误,因为它与第一个分配冲突。

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

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)

[如果确实需要一个变量来包含不同类型的值,则解决方法是在初始化时将其声明为Union类型,以便让mypy知道即使您给了它[现在str值,以后才具有Iterator[str]值是有效的:

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

当然,这意味着您要在该点之后使用该值进行的所有操作都必须考虑这两种类型!通常最好每个变量只有一个类型,这样以后就不必再进行大量的if isinstance...检查。
© www.soinside.com 2019 - 2024. All rights reserved.