Что такое представления в Python3.1? Они, похоже, ведут себя так же, как и итераторы, и они также могут быть реализованы в списках. Как отличаются итераторы и представления?
Просмотры в Python3.1?
Ответ 1
Из того, что я могу сказать, все еще привязано к объекту, из которого он был создан. Изменения в исходном объекте влияют на представление.
из 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'}
Ответ 2
Я бы рекомендовал вам читать this. Кажется, он лучше всего объясняет.
Насколько я могу судить, представления, похоже, больше связаны с dict
и могут быть принудительно переведены в list
s. Вы также можете сделать из них итератор, через который вы могли бы затем выполнить итерацию (в цикле for
или вызовом next
)
Обновление: обновленная ссылка с машины обратного пути
Ответ 3
Как отличаются итераторы и представления?
Я буду перефразировать вопрос как "какая разница между итерируемыми объектами и итератором"?
итеративный - объект, который может быть повторен (например, используется в цикле for
).
Итератор - это объект, который можно вызвать с помощью функции next()
, то есть реализует метод .next()
в Python2 и .__next__()
в python3. Итератор часто используется для переноса итерации и возврата каждого интересующего объекта. Все итераторы являются итерабельными, но обратное не обязательно верно (все итерации не являются итераторами).
Представления - это истребимые объекты, а не итераторы.
Посмотрите на некоторый код, чтобы увидеть различие (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')
A for
loop может использовать итерируемый объект и неявно получит итератор
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)