Python中的“iterable”、“iterator”和“iteration”是什么?它们是如何定义的?


当前回答

这是另一个使用collections.abc的视图。这个视图在第二次或以后可能会有用。

从集合。ABC我们可以看到下面的层次结构:

builtins.object
    Iterable
        Iterator
            Generator

例如,Generator是由Iterator派生的Iterable是由基对象派生的。

因此,

Every iterator is an iterable, but not every iterable is an iterator. For example, [1, 2, 3] and range(10) are iterables, but not iterators. x = iter([1, 2, 3]) is an iterator and an iterable. A similar relationship exists between Iterator and Generator. Calling iter() on an iterator or a generator returns itself. Thus, if it is an iterator, then iter(it) is it is True. Under the hood, a list comprehension like [2 * x for x in nums] or a for loop like for x in nums:, acts as though iter() is called on the iterable (nums) and then iterates over nums using that iterator. Hence, all of the following are functionally equivalent (with, say, nums=[1, 2, 3]): for x in nums: for x in iter(nums): for x in iter(iter(nums)): for x in iter(iter(iter(iter(iter(nums))))):

其他回答

迭代器是实现iter和next方法的对象。如果定义了这些方法,则可以使用for循环或推导式。

class Squares:
    def __init__(self, length):
        self.length = length
        self.i = 0
        
    def __iter__(self):
        print('calling __iter__') # this will be called first and only once
        return self
    
    def __next__(self): 
        print('calling __next__') # this will be called for each iteration
        if self.i >= self.length:
            raise StopIteration
        else:
            result = self.i ** 2
            self.i += 1
            return result

迭代器会耗尽。这意味着在你遍历项目之后,你不能重复,你必须创建一个新对象。假设你有一个类,它包含cities属性,你想要遍历。

class Cities:
    def __init__(self):
        self._cities = ['Brooklyn', 'Manhattan', 'Prag', 'Madrid', 'London']
        self._index = 0
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self._index >= len(self._cities):
            raise StopIteration
        else:
            item = self._cities[self._index]
            self._index += 1
            return item

类Cities的实例是一个迭代器。然而,如果你想在城市上重复,你必须创建一个新对象,这是一个昂贵的操作。你可以把这个类分成两个类:一个返回城市,第二个返回一个迭代器,它将城市作为初始参数。

class Cities:
    def __init__(self):
        self._cities = ['New York', 'Newark', 'Istanbul', 'London']        
    def __len__(self):
        return len(self._cities)



class CityIterator:
    def __init__(self, city_obj):
        # cities is an instance of Cities
        self._city_obj = city_obj
        self._index = 0
        
    def __iter__(self):
        return self
    
    def __next__(self):
        if self._index >= len(self._city_obj):
            raise StopIteration
        else:
            item = self._city_obj._cities[self._index]
            self._index += 1
            return item

现在如果我们需要创建一个新的迭代器,我们不需要再次创建数据,也就是城市。我们创建了cities对象并将其传递给迭代器。但我们仍在做额外的工作。我们可以通过只创建一个类来实现这一点。

Iterable是一个实现Iterable协议的Python对象。它只需要返回一个迭代器对象的新实例的__iter__()。

class Cities:
    def __init__(self):
        self._cities = ['New York', 'Newark', 'Istanbul', 'Paris']
        
    def __len__(self):
        return len(self._cities)
    
    def __iter__(self):
        return self.CityIterator(self)
    
    class CityIterator:
        def __init__(self, city_obj):
            self._city_obj = city_obj
            self._index = 0

        def __iter__(self):
            return self

        def __next__(self):
            if self._index >= len(self._city_obj):
                raise StopIteration
            else:
                item = self._city_obj._cities[self._index]
                self._index += 1
                return item

迭代器有__iter__和__next__,可迭代对象有__iter__,所以我们可以说迭代器也是可迭代对象,但它们是耗尽的可迭代对象。另一方面,迭代对象永远不会耗尽 因为它们总是返回一个新的迭代器,然后用于迭代

你注意到可迭代器代码的主要部分是在迭代器中,而可迭代器本身只不过是一个额外的层,允许我们创建和访问迭代器。

在可迭代对象上迭代

Python有一个内置的函数iter(),它调用__iter__()。当我们遍历一个可迭代对象时,Python调用iter(),它返回一个迭代器,然后它开始使用迭代器的__next__()来遍历数据。

注意,在上面的例子中,Cities创建了一个可迭代对象,但它不是一个序列类型,这意味着我们不能通过索引获得一个城市。为了解决这个问题,我们应该将__get_item__添加到Cities类中。

class Cities:
    def __init__(self):
        self._cities = ['New York', 'Newark', 'Budapest', 'Newcastle']
        
    def __len__(self):
        return len(self._cities)
    
    def __getitem__(self, s): # now a sequence type
        return self._cities[s]
    
    def __iter__(self):
        return self.CityIterator(self)
    
    class CityIterator:
        def __init__(self, city_obj):
            self._city_obj = city_obj
            self._index = 0

        def __iter__(self):
            return self

        def __next__(self):
            if self._index >= len(self._city_obj):
                raise StopIteration
            else:
                item = self._city_obj._cities[self._index]
                self._index += 1
                return item

迭代是一个通用术语,指一个接一个地获取某物的每一项。任何时候使用循环,显式或隐式,遍历一组项,这就是迭代。

在Python中,iterable和iterator有特定的含义。

iterable是一个具有__iter__方法的对象,该方法返回一个迭代器,或者定义了__getitem__方法,该方法可以接受从0开始的顺序索引(并在索引不再有效时引发IndexError)。iterable是一个你可以从中获取迭代器的对象。

迭代器是具有next (Python 2)或__next__ (Python 3)方法的对象。

无论何时在Python中使用for循环、map或列表推导式等,都会自动调用下一个方法从迭代器中获取每一项,从而完成迭代过程。

开始学习的一个好地方是教程的迭代器部分和标准类型页面的迭代器类型部分。在您理解了基础知识之后,请尝试函数式编程HOWTO中的迭代器部分。

Iterable:-可迭代的东西是可迭代的;比如序列,比如列表,字符串等等。 它也有__getitem__方法或__iter__方法。现在如果我们对该对象使用iter()函数,我们将得到一个迭代器。

迭代器:-当我们从iter()函数获得迭代器对象;我们调用__next__()方法(在python3中)或简单地调用next()(在python2中)来逐个获取元素。该类或该类的实例称为迭代器。

从文档:

迭代器的使用遍及并统一了Python。在后台,for语句在容器对象上调用iter()。该函数返回一个迭代器对象,该对象定义了__next__()方法,该方法每次访问容器中的一个元素。当没有更多的元素时,__next__()会引发一个StopIteration异常,告诉for循环终止。你可以使用next()内置函数调用__next__()方法;这个例子展示了它是如何工作的:

>>> s = 'abc'
>>> it = iter(s)
>>> it
<iterator object at 0x00A1DB50>
>>> next(it)
'a'
>>> next(it)
'b'
>>> next(it)
'c'
>>> next(it)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
    next(it)
StopIteration

一个类的前:-

class Reverse:
    """Iterator for looping over a sequence backwards."""
    def __init__(self, data):
        self.data = data
        self.index = len(data)
    def __iter__(self):
        return self
    def __next__(self):
        if self.index == 0:
            raise StopIteration
        self.index = self.index - 1
        return self.data[self.index]


>>> rev = Reverse('spam')
>>> iter(rev)
<__main__.Reverse object at 0x00A1DB50>
>>> for char in rev:
...     print(char)
...
m
a
p
s

iterable是一个具有iter()方法的对象,该方法返回一个迭代器。这是可以循环的。 示例:列表是可迭代的,因为我们可以遍历列表BUT不是迭代器 迭代器是一个可以从中获取迭代器的对象。它是一个具有状态的对象,以便在迭代过程中记住它所处的位置

要查看对象是否有iter()方法,可以使用下面的函数。

ls = ['hello','bye']
print(dir(ls))

输出

['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

正如你所看到的有iter(),这意味着它是一个可迭代对象,但不包含next()方法,这是迭代器对象的一个特征

无论何时在Python中使用for循环或map或列表推导式,都会自动调用next方法以从迭代中获取每一项

我不认为你能得到比文档更简单的东西,但我会尝试:

Iterable是可以被迭代的对象。在实践中,它通常是指一个序列,例如,有开始和结束的东西,以及一些贯穿其中所有项目的方法。 您可以将Iterator视为一个辅助伪方法(或伪属性),它给出(或保存)可迭代对象中的下一个(或第一个)项。(实际上它只是一个定义next()方法的对象) 《韦氏词典》对迭代这个词的定义可能是最好的解释:

B:重复指定的计算机指令序列 次数或直到满足条件-比较递归