Python3.1中的视图?

时间:2010-09-24 04:18:05

标签: python view python-3.x

Python3.1中的视图究竟是什么?它们的行为似乎与迭代器的行为类似,它们也可以实现为列表。迭代器和视图有何不同?

3 个答案:

答案 0 :(得分:12)

据我所知,视图仍然附加到它创建的对象上。对原始对象的修改会影响视图。

来自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'}

答案 1 :(得分:5)

我建议您阅读this。它似乎做了最好的解释。

据我所知,视图似乎与dict s更相关,可以强制进入list s。你也可以用它们创建一个迭代器,然后通过它迭代(在for循环中或通过调用next

更新:updated link from wayback machine

答案 2 :(得分:1)

  

迭代器和视图有何不同?

我将这个问题改为“ iterable 对象与迭代器”之间有什么区别?

iterable 是一个可以迭代的对象(例如在for循环中使用)。

迭代器是一个可以使用next()函数调用的对象,即它在Python2中实现.next()方法,在python3中实现.__next__()。迭代器通常用于包装 iterable 并返回每个感兴趣的项目。所有迭代器都是可迭代的,但反过来不一定是真的(所有迭代都不是迭代器)。

视图是可迭代的对象,而不是迭代器

让我们看一些代码来看看区别(Python 3):

"What's new in 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循环中重复使用。每次在此上下文中使用iterable时,它都会隐式返回一个新的迭代器(来自其__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循环可以使用iterable对象,并隐式获取迭代器

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)