Skip to main content
 首页 » 编程设计

python之成员资格测试结果与 list 和 csv.reader 不同

2025年05月04日17duanxz

如果我使用列表检查成员资格与使用 csv.reader 对象检查成员资格,我会得到不同的结果。 下面使用 unittest 模块。

成员(member)资格的 csv.reader 测试

with open("file.tab", 'rb') as f: 
    reader = csv.reader(f, delimiter='\t') 
    self.assertTrue(['1', '2', '3', '4'] in reader) 
    self.assertTrue(['2', '3', '4', '5'] in reader) 
    self.assertTrue(['3', '4', '5', '6'] in reader) 

成员列表测试

with open("file.tab", 'rb') as f: 
    reader = csv.reader(f, delimiter='\t') 
    reader = [record for record in reader] 
    self.assertTrue(['1', '2', '3', '4'] in reader) 
    self.assertTrue(['2', '3', '4', '5'] in reader) 
    self.assertTrue(['3', '4', '5', '6'] in reader) 

我知道 file.tab 包含我正在测试的三个记录的条目,但第三个断言在使用 csv.reader 时出现“False is not true”并在使用列表时通过。

csv.reader 是一个生成器; docs没有明确说,但因为我可以用尽它,我认为这意味着它是一个发电机。我的想法是这可能是原因,但以下测试只打印 true:

x = xrange(5) 
for m in range(5): 
    for n in range(5): 
        print m in x 
        print n in x 

这让我觉得使用生成器测试成员资格没有问题。

为什么当我使用 csv.reader 时第三个 assert 语句的计算结果与我使用列表时不同?

请您参考如下方法:

你运气不好 -- xrange 实际上不是一个生成器,而是它自己的一种特殊类型,它的行为是惰性的,因此可以让你误以为它是一个生成器。

>>> x = xrange(10) 
>>> 5 in x 
True 
>>> 5 in x 
True 

但是

>>> it = iter(range(10)) 
>>> 5 in it 
True 
>>> 5 in it 
False 

所以您的逻辑是正确的:reader 实例可以用完,但列表不能,这就是为什么成员测试可以根据内容返回不同答案的原因。请注意,虽然成员资格测试可能会短路,因此在出现积极结果的情况下它们不必耗尽:

>>> it = iter(range(10)) 
>>> 3 in it 
True 
>>> next(it) 
4