【问题标题】:Confusion about one example to check if an object is an iterator in Python关于一个检查对象是否是 Python 中的迭代器的示例的困惑
【发布时间】:2016-10-14 11:06:29
【问题描述】:

我在 stackoverflow 上阅读了一些关于如何检查对象是否是 Python 中的迭代器的帖子,但似乎它们并没有解决我的问题。我在 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!

为什么这一行检查变量 numbers 是否是一个迭代器?当visits = [15, 35, 80]时,iter(numbers) is iter(numbers)应该是真的吗?

【问题讨论】:

    标签: python iterator iterable


    【解决方案1】:

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

    来自iterator.__iter__() documentation

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

    因为iter(iterable) 总是返回本身,所以测试iter(obj) is iter(obj) 将是真的;两种情况都返回相同的对象。

    【讨论】:

      【解决方案2】:

      为了帮助您理解 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,则在 numbers 上调用 iter 将始终返回内部相同的对象:iter(numbers) is iter(numbers) 将是 True

      【讨论】:

        猜你喜欢
        • 2017-03-31
        • 1970-01-01
        • 2011-03-02
        • 1970-01-01
        • 2016-02-07
        • 2012-10-14
        • 1970-01-01
        • 1970-01-01
        • 2021-08-17
        相关资源
        最近更新 更多