Подтвердить что ты не робот

Просмотры в Python3.1?

Что такое представления в Python3.1? Они, похоже, ведут себя так же, как и итераторы, и они также могут быть реализованы в списках. Как отличаются итераторы и представления?

4b9b3361

Ответ 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)