如何使自定义对象可迭代?

时间:2014-02-09 21:46:57

标签: python list python-3.x iterable

我有list个自定义类对象(示例如下)。

使用:list(itertools.chain.from_iterable(myBigList))我想将所有stations子列表“合并”到一个大列表中。所以我认为我需要使自定义类成为可迭代的。

以下是我的自定义类的示例。

class direction(object) :
    def __init__(self, id) :
        self.id = id              
        self.__stations = list()

    def __iter__(self):
        self.__i = 0                #  iterable current item 
        return iter(self.__stations)

    def __next__(self):
        if self.__i<len(self.__stations)-1:
            self.__i += 1         
            return self.__stations[self.__i]
        else:
            raise StopIteration

我实施了__iter____next__,但似乎无效。他们甚至没有被召唤。

知道我能做错什么吗?

注意:使用Python 3.3

3 个答案:

答案 0 :(得分:20)

__iter__是您尝试迭代类实例时调用的内容:

>>> class Foo(object):
...     def __iter__(self):
...         return (x for x in range(4))
... 
>>> list(Foo())
[0, 1, 2, 3]

__next__是从__iter__返回的对象上调用的对象(在python2.x上,它是next,而不是__next__ - 我通常为它们设置别名,以便代码可以使用...):

class Bar(object):
   def __init__(self):
       self.idx = 0
       self.data = range(4)
   def __iter__(self):
       return self
   def __next__(self):
       self.idx += 1
       try:
           return self.data[self.idx-1]
       except IndexError:
           self.idx = 0
           raise StopIteration  # Done iterating.
   next = __next__  # python2.x compatibility.

答案 1 :(得分:4)

简单地实施__iter__就足够了。

class direction(object) :
    def __init__(self, id) :
        self.id = id              
        self.__stations = list()

    def __iter__(self):
        #return iter(self.__stations[1:]) #uncomment this if you wanted to skip the first element.
        return iter(self.__stations)


a = direction(1)
a._direction__stations= range(5)

b = direction(1)
b._direction__stations = range(10)

import itertools
print list(itertools.chain.from_iterable([a,b]))
print list(itertools.chain.from_iterable([range(5),range(10)]))

输出:

[0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

请参阅here了解_direction__stations

的原因
  

表单__spam的任何标识符(至少两个前导下划线,   最多一个尾随下划线)在文本上被替换为    classname _spam,其中classname是当前的类名,前导下划线被剥离。

答案 2 :(得分:3)

你也可以继承list

class Direction(list):
    def __init__(self, seq=[], id_=None):
        list.__init__(self,seq)
        self.id = id_ if id_ else id(self)

    def __iter__(self):
        it=list.__iter__(self) 
        next(it)                       # skip the first...
        return it  

d=Direction(range(10))
print(d)       # all the data, no iteration
# [0, 1, 2, 3, 4]

print (', '.join(str(e) for e in d))     # 'for e in d' is an iterator
# 1, 2, 3, 4

即跳过第一个。

也适用于嵌套列表:

>>> d1=Direction([range(5), range(10,15), range(20,25)])
>>> d1
[range(0, 5), range(10, 15), range(20, 25)]
print(list(itertools.chain.from_iterable(d1)))
[10, 11, 12, 13, 14, 20, 21, 22, 23, 24]