【问题标题】:What does iter() do to list?iter() 列出了什么?
【发布时间】:2018-10-12 10:40:06
【问题描述】:

我有这个代码:

a = ['animal', 'dog', 'car', 'bmw', 'color', 'blue']
a_iter = iter(a)

print(a)
print(a_iter)

print(dict(zip(a,a)))
print(dict(zip(a_iter,a_iter)))

输出是:

['animal', 'dog', 'car', 'bmw', 'color', 'blue']
<list_iterator object at 0x7f2d98b756d8>
{'dog': 'dog', 'car': 'car', 'animal': 'animal', 'color': 'color', 'blue': 'blue', 'bmw': 'bmw'}
{'car': 'bmw', 'color': 'blue', 'animal': 'dog'}

我不明白,为什么 a_iter 的 zip 与 a 的工作方式不同。 iter() 是做什么的,list 是可迭代的,那么为什么要使用 iter()?有人可以用一些很好的例子来解释我吗? google了一下,还是不明白。

【问题讨论】:

  • 迭代器是一种特殊类型的对象,它们是用来迭代的,所以它们速度很快并且不保存在内存中,它们主要用于for循环以提高速度,你总是可以通过list() 将迭代器转换为列表。

标签: python iterator python-3.5


【解决方案1】:

iter(l)l 返回一个迭代器对象。与next(i) 一起可用于迭代l 的元素。

代码:

for x in l: print(x)

等效于使用迭代器显式使用此代码:

i = iter(l)
while True:
    try:
        x = next(i)
        print(x)
    except StopIteration:
        break

注意,迭代器也可以用 for 循环遍历:

i = iter(l)
for x in i:
    print(x)

zip(a,b) 一次使用来自ab 的一个元素。

当 zip 的参数是一个序列时,它会为它创建自己的迭代器。

当参数是一个迭代器时,它只会消耗其中的元素。

当两个参数中的迭代器相同时,zip 的每次迭代将消耗迭代器的一个元素用于第一个参数,并消耗一个元素用于第二个参数。

>>> a = [1,2,3,4]
>>> b = [10,20,30,40]

>>> list(zip(a, b)) # zip two lists
[(1, 10), (2, 20), (3, 30), (4, 40)]

>>> list(zip(a, a)) # zip a list with itself
[(1, 1), (2, 2), (3, 3), (4, 4)]

>>> i1 = iter(a)
>>> i2 = iter(a)
>>> list(zip(i1, i2)) # same as above, but with iterators
[(1, 1), (2, 2), (3, 3), (4, 4)]

>>> i = iter(a)
>>> list(zip(i, i)) # same as above, but with the same iterator
[(1, 2), (3, 4)]

【讨论】:

  • 感谢您的精彩解释!
【解决方案2】:

iter() 对列表没有任何作用; list 对象有一个 __iter__ 方法,iter() 使用它来生成一个迭代器对象。该对象具有对原始列表的引用和索引;每次在迭代器中请求下一个值时,都会检索并返回当前索引处的值,并增加索引。

您可以使用next() 函数从迭代器中获取下一个值:

>>> a = ['animal', 'dog', 'car', 'bmw', 'color', 'blue']
>>> a_iter = iter(a)
>>> next(a_iter)  # get the next value
'animal'
>>> next(a_iter)  # get the next value
'dog'

请注意再次调用next() 会给您带来新的价值。您可以这样做直到迭代器完成:

>>> three_more = next(a_iter), next(a_iter), next(a_iter)
>>> next(a_iter)  # last one
'blue'
>>> next(a_iter)  # nothing left
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

列表迭代器对象保留原始列表对象;更改列表对象将反映在 next() 上生成的迭代器值:

>>> b = ['foo', 'bar']
>>> b_iter = iter(b)
>>> next(b_iter)
'foo'
>>> b[1] = 'spam'
>>> b
['foo', 'spam']
>>> next(b_iter)
'spam'

zip() 要求其每个参数中的下一个值,假定为 iterableszip() 给他们打电话iter()。对于a_iter等迭代器对象,iter(a_iter)返回迭代器本身(毕竟它已经是一个迭代器了):

>>> iter(a_iter)
<list_iterator object at 0x10e7b6a20>
>>> iter(a_iter) is a_iter
True

由于a_iter 将按顺序从原始列表中产生值,这意味着您会在字典中获得成对的元素,因为zip()对同一个对象的两个引用;您有效地将(next(a_iter), next(a_iter)) 创建为zip() 的迭代器步长值。另一方面,如果您传入两个对a 的引用,zip() 将调用iter()两次,创建两个单独的迭代器对象,每个迭代器对象都有自己的自己要跟踪的索引。

让我们详细了解一下。注意zip()产生了一个迭代器对象,所以我们可以验证在zip()上调用next()反过来会导致a_iter前进两次:

>>> a_iter = iter(a)
>>> a_iter_zip = zip(a_iter, a_iter)
>>> a_iter_zip   # a zip object is an iterator too
<zip object at 0x10e7ba8c8>
>>> next(a_iter_zip)  # get next value of a_iter, together with the next value of a_iter
('animal', 'dog')
>>> next(a_iter)  # the a-list iterator was advanced, so now we get 'car'
'car'
>>> next(a_iter_zip)  # now a_iter is at bmw, so we get bmw and color
('bmw', 'color')

迭代器是独立的对象,它们都有自己的索引:

>>> a_iter1 = iter(a)
>>> a_iter2 = iter(a)   # different iterator from a_iter1
>>> next(a_iter1), next(a_iter1)  # what zip() does
('animal', 'dog')
>>> next(a_iter2), next(a_iter2)  # iter2 is independent
('animal', 'dog')

所以当你使用zip(a, a) 时,真正发生的是zip() 调用iter(a) 两次,创建了两个新的迭代器,并且都用于创建输出:

>>> a_iter1 = iter(a)
>>> a_iter2 = iter(a)
>>> a_iter_1_and_2_zip = zip(a_iter1, a_iter2)
>>> next(a_iter_1_and_2_zip)  # values from a_iter1 and a_iter2
('animal', 'animal')
>>> next(a_iter_1_and_2_zip)  # moving in lockstep
('dog', 'dog')
>>> next(a_iter1)   # moving one of these two one step along, to 'car'
'car'
>>> next(a_iter_1_and_2_zip)   # so a_iter1 is one step ahead!
('bmw', 'car')
>>> next(a_iter1)   # another extra step
'color'
>>> next(a_iter_1_and_2_zip)   # so a_iter1 is two steps ahead!
('blue', 'bmw')

【讨论】:

    【解决方案3】:

    iter() 函数返回一个迭代器实例,我们可以在该实例上进行迭代以逐个获取所有值。它是内存高效函数,因为它只存储当前元素值。

    【讨论】:

      猜你喜欢
      • 2020-10-14
      • 1970-01-01
      • 1970-01-01
      • 2011-11-08
      • 1970-01-01
      • 2021-12-19
      • 2021-04-06
      相关资源
      最近更新 更多