我有一个脚本 - 一个生成器,它接受文件名或文件对象以及搜索词列表作为输入。生成器搜索文件的各行,并仅返回至少找到一个搜索词的那些行(整行)。
from io import TextIOBase
from typing import TextIO
import mimetypes
def find_lines(object_or_filename: TextIO | str, search_words: list) -> str:
if isinstance(object_or_filename, str) and mimetypes.guess_type(object_or_filename)[0] == 'text/plain':
with open(object_or_filename, 'r', encoding="utf-8") as file:
for line in file:
lower_line = line.lower()
if any(word.lower() in lower_line.split() for word in search_words):
yield line.strip()
elif isinstance(object_or_filename, TextIOBase):
for line in object_or_filename:
lower_line = line.lower()
if any(word.lower() in lower_line.split() for word in search_words):
yield line.strip()
有没有办法避免循环代码重复:
for line in file:
lower_line = line.lower()
if any(word.lower() in lower_line.split() for word in search_words):
yield line.strip()
我希望这个循环只使用一次,但不知道如何实现。
感谢Barmar的评论我做了一个上下文管理器
with open(object_or_filename, 'r', encoding="utf-8") as file:
contextlib.nullcontext
。
已经解释了在这个问题中:
contextlib.nullcontext
:
from contextlib import nullcontext
with get_stuff() if needs_with() else nullcontext() as gs:
# do nearly the same large block of stuff,
# involving gs or not, depending on needs_with()
注意
if needs_with() is False
,那么 gs
将是上下文块内的 None
。在这种情况下,如果您希望 gs
成为 something_else
,只需将 nullcontext()
替换为 nullcontext(something_else)
即可。
所以我的优化代码如下所示:
from io import TextIOBase
from typing import TextIO
import mimetypes
from contextlib import nullcontext
def find_lines(object_or_filename: TextIO | str, search_words: list) -> str:
if isinstance(object_or_filename, str) and mimetypes.guess_type(object_or_filename)[0] == 'text/plain' or \
isinstance(object_or_filename, TextIOBase):
with open(object_or_filename, 'r', encoding="utf-8") if (isinstance(object_or_filename, str)) else \
nullcontext(object_or_filename) as file:
for line in file:
lower_line = line.lower()
if any(word.lower() in lower_line.split() for word in search_words):
yield line.strip()