我在Python中有一个函数,当首先被调用时,将文件的内容读取到列表中并检查元素是否在该列表中。
def is_in_file(element, path):
with open(path, 'r') as f:
lines = [line.strip() for line in f.readlines()]
return element in lines
然而,当再次调用该函数时,不应再次读取该文件的内容;该函数应该记住第一次调用时lines
的值。
有没有办法在再次调用函数时保留函数的上下文?我不想让全局lines
不要丢弃上面的命名空间。我想这与使用生成器和yield
语句......
答案 0 :(得分:2)
脏黑客:将变量添加到函数对象并在那里存储值。
def is_in_file(element, path):
if not hasattr(is_in_file, "__lines__"):
with open(path, 'r') as f:
setattr(is_in_file, "__lines__", [line.strip() for line in f.readlines()])
return element in is_in_file.__lines__
答案 1 :(得分:2)
我的观点是,正确的方法是将其封装在一个类中。路径在实例创建时设置,方法调用使用行列表。这样你甚至可以同时拥有不同的文件:
class finder:
def __init__(self, path):
with open(path, 'r') as f:
self.lines = [line.strip() for line in f]
def is_in_file(self, element):
return element in lines
这不完全是你所要求的,但更多的是OO。
答案 2 :(得分:1)
您可以将行保存在使用可变默认值声明的关键字参数中:
def is_in_file(element, path, lines=[]):
if lines:
return element in lines
with open(path, 'r') as f:
lines += [line.strip() for line in f.readlines()]
return element in lines
<强> 警告: 强> 你必须确保只用一个文件调用这个函数;如果你用第二个文件调用它,它将不会打开它并继续根据打开的第一个文件返回值。
更灵活的解决方案可能是使用行字典,其中每个新文件可以使用路径作为键打开一次并存储;然后,您可以使用不同的文件调用该函数,并在记忆内容时获得正确的结果。
def is_in_file(element, path, all_lines={}):
try:
return element in all_lines[path]
except KeyError:
with open(path, 'r') as f:
all_lines[path] = [line.strip() for line in f.readlines()]
return element in lines
创建一个类来封装文件的内容,就像@SergeBallesta提出的那样;虽然它没有完全满足您的要求,但从长远来看,它可能是更好的解决方案。
答案 3 :(得分:1)
使用functools.lru_cache
装饰器设置一个辅助函数,该函数只读取任何给定文件一次,然后存储结果。
from functools import lru_cache
@lru_cache(maxsize=1)
def read_once(path):
with open(path) as f:
print('reading {} ...'.format(path))
return [line.strip() for line in f]
def in_file(element, path):
return element in read_once(path)
演示:
>>> in_file('3', 'file.txt')
reading file.txt ...
True
>>> in_file('3', 'file.txt')
True
>>> in_file('3', 'anotherfile.txt')
reading anotherfile.txt ...
False
>>> in_file('3', 'anotherfile.txt')
False
这具有以下重要优势:每次都不必使用相同的文件名调用in_file
。
如果您希望在任何给定时间缓存多个文件,可以将maxsize
参数调整为更高的数字。
最后:如果您感兴趣的是会员资格测试,请考虑设置read_once
的返回值。
答案 4 :(得分:1)
这个答案提出了一个类似于Serge Ballesta的想法的课程。
区别在于它完全像功能,因为我们使用它的just before subscribe
just after subscribe
got value 1
got value 2
got value 3
done
方法而不是点符号来进行搜索。
此外,您可以根据需要添加任意数量的可搜索文件。
设定:
__call__
用法
class in_file:
def __init__(self):
self.files = {}
def add_path(self, path):
with open(path) as f:
self.files[path] = {line.strip() for line in f}
def __call__(self, element, path):
if path not in self.files:
self.add_path(path)
return element in self.files[path]
in_file = in_file()