Python3.1中的视图?

20

Python3.1中的“views”指的是什么?它们的行为看起来与迭代器类似,也可以转换为列表。那么迭代器和视图有什么不同呢?

3个回答

13
据我所知,视图仍然与创建自身的对象相关联。对原始对象的修改会影响该视图。
docs(有关字典视图)了解:
>>> 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'}

5
我建议你阅读这篇文章。它似乎最能清楚地解释。
就我所知,视图似乎更与字典相关,并且可以被强制转换为列表。你也可以通过它们创建一个迭代器,通过迭代器你可以在for循环中或通过调用next来迭代。
更新:来源于Web存档机的更新链接

1
@AnirudhRamanathan:我已经更新了链接。感谢您让我知道。 - inspectorG4dget

2
迭代器和视图有什么不同?
我将这个问题重新表述为“可迭代对象和迭代器之间的区别是什么”?
一个可迭代对象是一个可以被迭代的对象(例如,在for循环中使用)。
一个迭代器是一个可以使用next()函数调用的对象,即它在Python2中实现了.next()方法,在Python3中实现了.__next__()。迭代器通常用来包装一个可迭代对象并返回每个感兴趣的项。所有迭代器都是可迭代的,但反过来不一定成立(所有可迭代的对象都不是迭代器)。
视图是可迭代对象,而不是迭代器
让我们看一些代码来理解这个区别(Python 3):
Python 3中的"新功能"文档非常明确,指出哪些函数返回迭代器。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 ...

`dict.items()`以及`dict.keys()`和`dict.values()`在Python 3中也不返回迭代器。
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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接