Новые итерируемые объекты
>>> zip(‘abc’, ‘xyz’) # Итерируемый объект в Python 3.0 (список в 2.6)
<zip object at 0x02E66710>
>>> list(zip(‘abc’, ‘xyz’)) # Принудительное создание списка
[(‘a’, ‘x’), (‘b’, ‘y’), (‘c’, ‘z’)] # результатов для отображения в 3.0
-----------------------------------------------------------------
Итератор range:
В версии 3.0 функция range возвращает итератор, который не создает сразу весь список целых чисел в заданном диапазоне, а генерирует их по требованию. Она действует точно так же, как прежняя функция xrange в версии 2.X и в случае, когда необходимо получить сразу весь список с результатами (например, для отображения), обращение к ней следует обернуть в вызов функции list(range(...)):
C:\\misc> c:\python30\python
>>> R = range(10) # range возвращает итератор, а не список
>>> R
range(0, 10)
>>> I = iter(R) # Вернет итератор для диапазона
>>> next(I) # Переход к следующему результату
0 # То же происходит в циклах for, генераторах списков и пр.
>>> next(I)
1
>>> next(I)
2
>>> list(range(10)) # При необходимости можно принудительно
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] # сгенерировать список
-----------------------------------------------------------------
Итераторы map,zip и filter:
Встроенные функции map, zip и filter возвращают итераторы вместо того, чтобы воспроизводить сразу весь список с результатами.
Однако, в отличие от функции range, их результаты сами и являются этими итераторами, – после однократного получения отдельного результата этот результат исчезает.
Пример использования встроенной функции map:
>>> M = map(abs, (-1, 0, 1)) # map возвращает итератор, а не список
>>> M
<map object at 0x0276B890>
>>> next(M) # Непосредственное использование итератора:
1 # результаты исчерпываются безвозвратно.
>>> next(M) # Они не поддерживают функцию len()
0 # и операцию индексирования
>>> next(M)
1
>>> next(M)
StopIteration
>>> for x in M: print(x) # Теперь итератор map пуст:
... # возможен только один проход
>>> M = map(abs, (-1, 0, 1)) # Чтобы выполнить второй проход,
# необходимо
# снова создать итератор
>>> for x in M: print(x) # В контексте итераций функция next()
... # вызывается автоматически
1
0
1
>>> list(map(abs, (-1, 0, 1))) # При необходимости можно получить
# сразу
[1, 0, 1] # весь список с результатами
-----------------------------------------------------------------
Пример встроенной функции zip:
>>> Z = zip((1, 2, 3), (10, 20, 30)) # zip также возвращает итератор, который
>>> Z # позволяет выполнить только один проход
<zip object at 0x02770EE0>
>>> list(Z)
[(1, 10), (2, 20), (3, 30)]
>>> for pair in Z: print(pair) # Результаты исчерпываются после
... # первого прохода
>>> Z = zip((1, 2, 3), (10, 20, 30))
>>> for pair in Z: print(pair) # Итератор можно использовать
... # вручную или автоматически
(1, 10)
(2, 20)
(3, 30)
>>> Z = zip((1, 2, 3), (10, 20, 30))
>>> next(Z)
(1, 10)
>>> next(Z)
(2, 20)
-----------------------------------------------------------------
Поддержка множественных и единственных итераторов:
Возможность применение к результату несколько итераторов.
>>> R = range(3) # Объект диапазона позволяет получить множество итераторов
>>> next(R)
TypeError: range object is not an iterator
>>> I1 = iter(R)
>>> next(I1)
0
>>> next(I1)
1
>>> I2 = iter(R) # Два итератора для одного диапазона
>>> next(I2)
0
>>> next(I1) # I1 находится в другой позиции, не совпадающей с позицией I2
2
Функции zip, map и filter, напротив, не поддерживают возможность получения
различных активных итераторов для одного и того же результата:
>>> Z = zip((1, 2, 3), (10, 11, 12))
>>> I1 = iter(Z)
>>> I2 = iter(Z) # Два итератора для одного и того же результата
# zip
>>> next(I1)
(1, 10)
>>> next(I1)
(2, 11)
>>> next(I2) # Позиции итераторов I2 и I1 совпадают!
(3, 12)
>>> M = map(abs, (-1, 0, 1)) # То же относится к функции map (и filter)
>>> I1 = iter(M); I2 = iter(M)
>>> print(next(I1), next(I1), next(I1))
1 0 1
>>> next(I2)
StopIteration
>>> R = range(3) # А для объекта диапазона можно получить
>>> I1, I2 = iter(R), iter(R) # множество итераторов
>>> [next(I1), next(I1), next(I1)]
[0 1 2]
>>> next(I2)
0
-----------------------------------------------------------------
Итераторы представлений словарей:
Методы keys, values и items слова
рей возвращают итерируемые объекты представлений, которые возвращают
результаты по одному за раз вместо того, чтобы сразу создавать списки с ре
зультатами.
>>> D = dict(a=1, b=2, c=3)
>>> D
{‘a’: 1, ‘c’: 3, ‘b’: 2}
>>> K = D.keys() # Объект представления в версии 3.0 не является списком
>>> K
<dict_keys object at 0x026D83C0>
>>> next(K) # Представления не являются итераторами
TypeError: dict_keys object is not an iterator
>>> I = iter(K) # Из представлений можно получить итераторы
>>> next(I) # и с их помощью выполнять итерации вручную,
‘a’ # но они не поддерживают функцию len()
>>> next(I) # и операцию доступа к элементам по индексу
‘c’
>>> for k in D.keys(): print(k, end=’ ‘) # Во всех итерационных контекстах
... # итераторы используются
a c b # автоматически
-----------------------------------------------------------------
Доступ по индексу:
>>> K = D.keys()
>>> list(K) # При необходимости всегда можно получить полный список
[‘a’, ‘c’, ‘b’]
>>> V = D.values() # То же относится к представлениям values() и items()
>>> V
<dict_values object at 0x026D8260>
>>> list(V)
[1, 3, 2]
>>> list(D.items())
[(‘a’, 1), (‘c’, 3), (‘b’, 2)]
>>> for (k, v) in D.items(): print(k, v, end=’ ‘)
...
a 1 c 3 b 2
-----------------------------------------------------------------
Пример когда нет никакой необходимости вызывать метод keys:
>>> D # Словари поддерживают собственные итераторы,
{‘a’: 1, ‘c’: 3, ‘b’: 2} # возвращающие следующий ключ в каждой итерации
>>> I = iter(D)
>>> next(I)
‘a’
>>> next(I)
‘c’
>>> for key in D: print(key, end=’ ‘) # Нет никакой необходимости
# вызывать
... # метод keys(), однако этот
# метод
a c b # в версии 3.0 также
# возвращает итератор!
----------------------------------------------------------------
И на последок:
>>> D
{‘a’: 1, ‘c’: 3, ‘b’: 2}
>>> for k in sorted(D.keys())): print(k, D[k], end=’ ‘)
...
a 1 b 2 c 3
>>> D
{‘a’: 1, ‘c’: 3, ‘b’: 2}
>>> for k in sorted(D): print(k, D[k], end=’ ‘) # Лучший способ
... # сортировки ключей
a 1 b 2 c 3
Добавим теории:
• С помощью инструкции yield пользовательские функции можно превратить в итерируемые функции-генераторы.
• Генераторы списков можно трансформировать в итерируемые выражения генераторы, заключив их в круглые скобки.
• В пользовательские классы можно добавить поддержку итераций с помощью методов перегрузки операторов __iter__ или __getitem__.
Комментариев нет:
Отправить комментарий