鉴于项目编号列表,我正在尝试搜索带有最近项目编号列表的文本文件,并在最近的列表中标识任何项目编号。然后,我想要添加最近列表中尚未包含的任何项目。
我的代码如下,它似乎没有在文本文件中找到任何内容。为什么它不起作用?
def filter_recent_items(items):
recentitems = []
with open('last 600 items.txt', 'r+') as f:
for item in items:
if item['ID'] in f:
print 'In! --', item['ID']
else:
recentitems.append(item['ID'])
print 'Out ---', item['ID']
for item in recentitems:
f.write("%s\n" % item)
items = [ {'ID': 1}, {'ID': 'test2'} ]
filter_recent_items(items)
例如,我的文本文件是:
test2
test1
1
但上面的代码返回
Out --- 1
Out --- test2
答案 0 :(得分:6)
问题在于如何检查指定文本是否存在。在您的代码中f
是一个文件对象,用于读取和写入文件。它不包含文件的内容。所以当你检查是否
str in f
它没有检查你的想法。 (详见下文。)
相反,您需要读取文件的行,然后遍历这些行并检查必要的字符串。实施例
with open('last 600 items.txt', 'r+') as f:
lines = f.readlines()
for l in lines:
# check within each line for the presence of the items
在上面的代码中,f.readlines()
使用文件对象来读取文件的内容并返回字符串列表,这些字符串是文件中的行。
已编辑(感谢Peter Wood)
在Python中,当您使用语法x in y
时,它会检查两件事:
案例1 :首先检查y
是否有__contains__(b)
方法。如果是,则返回y.__contains__(x)
的结果。
案例2 但是,如果y
不有<{1}}方法,但确实定义了__contains__
方法,相反,Python使用那个方法迭代__iter__
的内容并返回y
,如果在任何一点上迭代的值等于True
。否则,它返回x
。
如果我们以您的代码为例,在某一点上,它会检查语句False
的真实性。此处"test2" in f
是f
类型的对象。 (Python File Object Description)。文件对象属于案例2(即他们不有file
,他们做有__contains__
。
因此,代码将遍历每一行,并查看输入字符串是否与文件中的任何行相等。由于每一行都以char __iter__
结尾,因此您的字符串永远不会返回\n
。
详细说明,虽然True
会返回"test2" in "test2\n"
,但此处实际执行的测试是:True
,即"test2" == "test2\n"
。
您可以手动测试文件的工作原理。例如,如果我们想查看False
是否应该返回"test2" in f
:
True
您会注意到它打印出每一行(包括末尾的换行符),with open(filename) as f:
x = iter(f)
while(True):
try:
line = x.next()
except:
break
print(line)
print(line == "test2")
的结果始终为line == "test2"
。
如果我们尝试:False
,则结果为"test2\n" in f
。
结束修改
答案 1 :(得分:2)
正如其他人所说,if "somestring" in f
将永远失败。 f
是一个文件对象,当您遍历它时,会生成一行文本。这些LINES中的一个或多个可能包含您的文本,因此您可以这样做:
if any("targetstring" in line for line in f):
# success
与f.read()
或f.readlines()
方法相比,这是一种节省内存的方法,它们在执行任何操作之前都将整个文件流式传输到内存中。
@PeterWood在评论中指出,你的一些目标字符串实际上并不是字符串。你也应该看到这一点。 all(isinstance(item["ID"], str) for item in items)
应为True
。
答案 2 :(得分:1)
打印出您的数据存储 f 。首先,我希望你有嵌入的换行符,以防止项匹配:“1”与“1 \ n”不匹配。其次,请注意**打开“给你一个生成器,而不是列表或元组。你不能多次扫描列表。在你以某种方式迭代它之前,你没有它的数据。
您需要使用代码将所有元素放入内存,例如
content = f.read().split("\n")
for item in items:
if item["ID" in content: