有趣的 MYPY 行为——关于 difflib 的警告只有一次
Interesting MYPY behavior - warning about difflib only once
我有以下代码:
"""
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 中的读取行有关,但为什么在将差异工作写入 HTML 文件时没有发生?
更新:
我已经更新了代码,但感谢 Samwise 定义了 delta 并解决了问题,一切正常,没有 mypy 错误。我肯定会开始真正深入研究打字。
第一次为变量赋值(在本例中为 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...
检查。
我有以下代码:
"""
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 中的读取行有关,但为什么在将差异工作写入 HTML 文件时没有发生?
更新: 我已经更新了代码,但感谢 Samwise 定义了 delta 并解决了问题,一切正常,没有 mypy 错误。我肯定会开始真正深入研究打字。
第一次为变量赋值(在本例中为 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...
检查。