关于一个示例的混淆,以检查对象是否是Python中的迭代器

时间:2016-06-13 21:54:31

标签: python iterator iterable

我已经阅读了有关如何检查对象是否是Python中的迭代器的stackoverflow上的一些帖子,但似乎它们没有解决我的问题。我在 Effective Python

一书中有这个例子
def normalize_defensive(numbers):
   if iter(numbers) is iter(numbers):  # An iterator — bad!
       raise TypeError(‘Must supply a container’)
   total = sum(numbers)
   result = []
   for value in numbers:
       percent = 100 * value / total
       result.append(percent)
   return result

使用:

visits = [15, 35, 80]
normalize_defensive(visits)  # No error
visits = ReadVisits(path)  # ReadVisits is a class with an __iter__ method.
normalize_defensive(visits)  # No error
it = iter(visits)
normalize_defensive(it)
>>>
TypeError: Must supply a container

所以我的问题就在这一行:

if iter(numbers) is iter(numbers):  # An iterator — bad!

为什么这行检查变量号是否是迭代器?当访问次数= [15,35,80]时,iter(numbers) is iter(numbers)

是否属实?

2 个答案:

答案 0 :(得分:2)

当您调用 iterable 时,在这样的对象上调用iter()将始终生成 new 迭代器对象。但是在迭代器上调用iter()将始终返回相同的对象;它是iterator protocol的要求。

来自iterator.__iter__() documentation

  

返回迭代器对象本身。这是允许容器和迭代器与forin语句一起使用所必需的。

由于iter(iterable)始终返回本身,因此测试iter(obj) is iter(obj)将为真;在这两种情况下都返回相同的对象。

答案 1 :(得分:0)

为了帮助您了解Martijn的解释,请查看以下内容:

>>> numbers = [15, 35, 80]
>>> it  = iter(numbers)
>>> it2 = iter(numbers)
>>> it3 = iter(it)
>>> id(it1)
51123792
>>> id(it2)
51056464    # id of it2 is different from it1
>>> id(it3) 
51123792    # iterator of iterator it3 has the same id as iterator it1

因此,如果numbersiterator,则iter上的numbers调用将始终返回内部相同的对象:iter(numbers) is iter(numbers)将为True }。