这段带有Python if语句和isinstance的代码可以调整以避免循环重复吗?

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

我有一个脚本 - 一个生成器,它接受文件名或文件对象以及搜索词列表作为输入。生成器搜索文件的各行,并仅返回至少找到一个搜索词的那些行(整行)。

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()

我希望这个循环只使用一次,但不知道如何实现。

python loops text contextmanager isinstance
1个回答
0
投票

感谢Barmar的评论我做了一个上下文管理器

with open(object_or_filename, 'r', encoding="utf-8") as file:

可选用

contextlib.nullcontext
。 已经解释了在这个问题中

Python 3.7 及以上版本

Python 3.7 引入

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()
© www.soinside.com 2019 - 2024. All rights reserved.