iter(x)和x .__ iter __()有什么区别?

时间:2015-07-23 14:49:14

标签: python

iter(x)x.__iter__()之间的区别是什么?

根据我的理解,他们都返回一个listiterator对象,但在下面的示例中,我注意到它们不相等:

x = [1, 2, 3]
y = iter(x)
z = x.__iter__()
y == z
False

有什么东西我不了解迭代器对象吗?

5 个答案:

答案 0 :(得分:7)

Iter对象不具备基于此类事物的相等性。

看到iter(x) == iter(x)也返回False。这是因为iter函数(调用__iter__)返回一个不会重载__eq__的iter对象,因此只有当两个对象相同时才返回True

如果没有超载,==is比较相同。

此外,x.__iter__().__class__ is iter(x).__class__显示,在这种情况下,它们返回相同类型的对象。

答案 1 :(得分:1)

通过调用iter(x)x.__iter__()创建迭代器没有区别。您正在制作2个listiterator个对象并进行比较。比较它们以查看它们是否与它们产生的迭代器对象相同。

>>> test = [1,2,3,4]
>>> iter(test)
<listiterator object at 0x7f85c7efa9d0>
>>> test.__iter__()
<listiterator object at 0x7f85c7efaa50>

您可以看到生成了2个不同的对象。

如果您同时拨打iter(test)两次也是一样。

您可以通过将两个变量指向同一个对象来使它们相同。

>>> test = [1,2,3,4]
>>> iter_one = iter(test)
>>> iter_two = iter_one
>>> print iter_one == iter_two
True
>>> iter_one.next()
1
>>> iter_two.next()
2

你可以看到他们都引用了同一个对象。

您可以通过再次将它们转换回列表来检查差异迭代器是否产生相同的输出。

>>> print list(iter(test)) == list(test.__iter__())
True

答案 2 :(得分:1)

它们总是不完全相同。来自documentation -

  

iter(o [,sentinel])

     

返回一个迭代器对象。根据第二个参数的存在,第一个参数的解释非常不同。如果没有第二个参数,o必须是支持迭代协议(__iter__()方法)的集合对象,或者它必须支持序列协议(__getitem__()方法,整数参数从0开始)。 / p>

但是对于您的列表案例,它们是相似的,就像iter()内部调用__iter__()一样。但是它们都返回不同的迭代器对象,你可以分别迭代两个返回值,因此它们不相等。

显示迭代器的一般情况的示例 -

In [13]: class CA:
   ....:     def __iter__(self):
   ....:         print('Inside __iter__')
   ....:         return iter([1,2,3,4])
   ....:

In [14]: c = CA()

In [15]: iter(c)
Inside __iter__
Out[15]: <list_iterator at 0x3a13d68>

In [16]: c.__iter__()
Inside __iter__
Out[16]: <list_iterator at 0x3a13908>    #see that even the ids are different for the list_iterator objects.

In [17]: class BA:
   ....:     def __getitem__(self,i):
   ....:         print('Inside __getitem__')
   ....:         return i+5
   ....:

In [18]: b = BA()

In [19]: iter(b)
Out[19]: <iterator at 0x3a351d0>

In [20]: x = iter(b)

In [21]: next(x)
Inside __getitem__
Out[21]: 5

In [23]: next(x)
Inside __getitem__
Out[23]: 6

示例显示每次调用iter()都会返回一个不同的迭代器对象,可以单独迭代 -

In [24]: i = iter(c)
Inside __iter__

In [25]: j = iter(c)
Inside __iter__

In [26]: for x in i:
   ....:     pass
   ....:

In [27]: next(i)
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-27-bed2471d02c1> in <module>()
----> 1 next(i)

StopIteration:

In [28]: next(j)
Out[28]: 1

如上所示,即使i已用尽,j仍处于起始位置,因此您可以看到两者都是完全不同的对象(具有不同的状态)。

答案 3 :(得分:1)

列表支持Python中的多个迭代器,因此每次调用它上面的iter()将返回一个新的迭代器对象,并且它们没有自己的__eq__方法,因此最终Python最后使用他们的ID来比较它们,当然这是不同的。

>>> type(iter([])).__eq__
<method-wrapper '__eq__' of type object at 0x100646ea0>
>>> object.__eq__
<method-wrapper '__eq__' of type object at 0x100650830>

一个实例仅支持一个迭代器的类:

class A(object):
    def __iter__(self):
        return self

    def next(self):
        pass

a = A()
y = iter(a)
z = a.__iter__()
print y == z # will print True

也可以为不同的迭代器获取True,但前提是返回比较时比较相等的迭代器类型。

据说,永远不要像iter(obj)那样调用obj.__iter__(),因为在这种情况下,它不会在类上查找__iter__,而是在实例上查找__iter__第一:

class A(object):
    def __init__(self):
        self.__iter__ = lambda: iter(())
    def __iter__(self):
        return iter([])


a = A()
print a.__iter__()
print iter(a)
# output
<tupleiterator object at 0x10842b250>
<listiterator object at 0x10842b2d0>

答案 4 :(得分:0)

每当你调用iter(x)时,你将获得一个新的Iterator实例,它将指向同一个对象。当您执行a = iter(x)b = iter(x)时,您有两个迭代器,它们指向一个对象。由于Iterator没有将__eq__()定义为指向的对象的相等性,而是迭代器实例,因此即使iter(x) == iter(x)也将返回false。

iter()基本上调用对象的 __ iter __()函数:

Built-in Functions

  

如果没有第二个参数,o必须是支持迭代协议的集合对象( __ iter __ ()方法),或者它必须支持序列协议