在构造函数中分配__iter__的类未被识别为迭代器

时间:2013-10-22 03:38:39

标签: python list iterable

关于迭代器的一个奇怪的问题。在调查一个不同的问题时,我发现了以下内容。这是一个可行的迭代:

class CacheGen(object):
    def __init__(self, iterable):
        if isinstance(iterable, (list, tuple, dict)):
            self._myiter = iterable
        else:
            self._myiter = list(iterable)
    def __iter__(self):
        return self._myiter.__iter__()
    def __contains__(self, key):
        return self._myiter.__contains__(key)
    def __getitem__(self, key):
        return self._myiter.__getitem__(key)

这是一个类似的迭代:

class CacheGen2(object):
    def __init__(self, iterable):
        if isinstance(iterable, (list, tuple, dict)):
            self._myiter = iterable
        else:
            self._myiter = list(iterable)
        self.__iter__ = self._myiter.__iter__
        self.__contains__ = self._myiter.__contains__
        self.__getitem__ = self._myiter.__getitem__

请注意,他们实际上是在做同样的事情,但是一个委托,另一个只是将我的类构造函数分配给列表。有什么想法吗?请注意,它在类中有一个 iter 函数,我可以直接调用它并获得一个有效的迭代器,但是'normal'函数不起作用。

xr = xrange(100)
cg = CacheGen(xr)
list(cg)
[0,1,2,3...

cg2 = CacheGen2(xr)
list(cg2)
TypeError                                 Traceback (most recent call last)
<ipython-input-83-1f4da2c55acb> in <module>()
----> 1 list(cg2)

TypeError: 'CacheGen2' object is not iterable

cg2.__iter__
<method-wrapper '__iter__' of list object at 0x0000000006695C08>

cg2.__iter__()
<listiterator at 0x669c438>

iter(cg2)
TypeError                                 Traceback (most recent call last)
<ipython-input-86-b62853ce1dab> in <module>()
----> 1 iter(cg2)

TypeError: 'CacheGen2' object is not iterable

3 个答案:

答案 0 :(得分:10)

__iter__等魔术方法会在类上查找,而不是实例,因此无法在self上分配它们。它们必须存在于课堂上。

答案 1 :(得分:1)

正确的做法是:

class CacheGen(object):

    def __init__(self, iterable):
        if isinstance(iterable, (list, tuple, dict)):
            self._myiter = iterable
        else:
            self._myiter = list(iterable)

    def __iter__(self):
        for value in self._myiter:
            yield value
    ...

答案 2 :(得分:1)

如果您想创建自己的Iterator类,

您的班级必须覆盖以下方法

def __iter__(self)

def next(self)

然后只将您的类视为迭代器

迭代器的简单示例是,

class MyIter(object):
    def __init__(self, val):
        self.val = val

    def __iter__(self):
        return self

    def next(self):
        if self.val >= 5:
            raise StopIteration
        self.val += 1
        return self.val

print list(MyIter(0))