Python3.1中的“views”指的是什么?它们的行为看起来与迭代器类似,也可以转换为列表。那么迭代器和视图有什么不同呢?
Python3.1中的“views”指的是什么?它们的行为看起来与迭代器类似,也可以转换为列表。那么迭代器和视图有什么不同呢?
>>> dishes = {'eggs': 2, 'sausage': 1, 'bacon': 1, 'spam': 500}
>>> keys = dishes.keys()
>>> values = dishes.values()
>>> # iteration
>>> n = 0
>>> for val in values:
... n += val
>>> print(n)
504
>>> # keys and values are iterated over in the same order
>>> list(keys)
['eggs', 'bacon', 'sausage', 'spam']
>>> list(values)
[2, 1, 1, 500]
>>> # view objects are dynamic and reflect dict changes
>>> del dishes['eggs']
>>> del dishes['sausage']
>>> list(keys)
['spam', 'bacon']
>>> # set operations
>>> keys & {'eggs', 'bacon', 'salad'}
{'bacon'}
for
循环中或通过调用next
来迭代。for
循环中使用)。next()
函数调用的对象,即它在Python2中实现了.next()
方法,在Python3中实现了.__next__()
。迭代器通常用来包装一个可迭代对象并返回每个感兴趣的项。所有迭代器都是可迭代的,但反过来不一定成立(所有可迭代的对象都不是迭代器)。map()
、filter()
和zip()
肯定返回迭代器,而dict.items()
、dict.values()
和dict.keys()
被认为返回视图对象。至于range()
,尽管对其返回值的描述缺乏精确性,但我们知道它不是迭代器。map()
来将列表中的所有数字加倍。m = map(lambda x: x*2, [0,1,2])
hasattr(m, '__next__')
# True
next(m)
# 0
next(m)
# 2
next(m)
# 4
next(m)
# StopIteration ...
filter()
函数提取所有奇数f = filter(lambda x: x%2==1, [0,1,2,3,4,5,6])
hasattr(f, '__next__')
# True
next(f)
# 1
next(f)
# 3
next(f)
# 5
next(f)
# StopIteration ...
range()
以相同的方式生成数字序列。r = range(3)
hasattr(r, '__next__')
# False
next(r)
# TypeError: 'range' object is not an iterator
it = iter(r)
next(it)
# 0
next(it)
# 1
next(it)
# 2
next(it)
# StopIteration ...
d = {'a': 0, 'b': 1, 'c': 2}
items = d.items()
hasattr(items, '__next__')
# False
it = iter(items)
next(it)
# ('b', 1)
next(it)
# ('c', 2)
next(it)
# ('a', 0)
for
循环中使用,而可迭代对象可以在后续的for
循环中重复使用。每次在此上下文中使用可迭代对象时,它都会隐式地返回一个新的迭代器(从其__iter__()
方法中返回)。以下自定义类通过输出列表对象和返回的迭代器对象的内存id
来演示这一点:class mylist(list):
def __iter__(self, *a, **kw):
print('id of iterable is still:', id(self))
rv = super().__iter__(*a, **kw)
print('id of iterator is now:', id(rv))
return rv
l = mylist('abc')
for
循环可以使用可迭代对象,并会隐式地获取一个迭代器。for c in l:
print(c)
# id of iterable is still: 139696242511768
# id of iterator is now: 139696242308880
# a
# b
# c
for
循环可以使用同样的可迭代对象,但会获得另一个迭代器。for c in l:
print(c)
# id of iterable is still: 139696242511768
# id of iterator is now: 139696242445616
# a
# b
# c
it = iter(l)
# id of iterable is still: 139696242511768
# id of iterator is now: 139696242463688
for c in it:
print(c)
# a
# b
# c
for c in it:
print(c)
for c in it:
print(c)