Итераторы, основы
Итераторы мы будем рассматривать на примере работы с файлами, как один из типов данных.
Например вызывая метод readline, мы перемещаемся к следующей строке:
>>> f = open(‘script1.py’) # Прочитать 4 строки из файла сценария
>>> f.readline() # Метод readline загружает одну строку
‘import sys\n’
>>> f.readline()
‘print(sys.path)\n’
>>> f.readline()
‘x = 2\n’
>>> f.readline()
‘print(2 ** 33)\n’
>>> f.readline() # Вернет пустую строку по достижении конца файла
‘’
-----------------------------------------------------------------
Далее тот же самый пример, только используем функцию __next__().
По достижении конца файла метод __next__ возбуждает встроенное исключение
StopIteration вместо того, чтобы возвращать пустую строку:
>>> f = open(‘script1.py’) # Метод __next__ загружает одну строку
>>> f.__next__()# и возбуждает исключение по достижении конца
# файла
‘import sys\n’
>>> f.__next__()
‘print(sys.path)\n’
>>> f.__next__()
‘x = 2\n’
>>> f.__next__()
‘print(2 ** 33)\n’
>>> f.__next__()
Traceback (most recent call last):
...текст сообщения об ошибке опущен...
StopIteration
Подобные объекты в языке Python считаются итерируемыми.
-----------------------------------------------------------------
Цикл for может автоматически вызывать метод __next__ для перемещения к следующей строке в каждой итерации.
Например, следующий фрагмент читает содержимое файла строку за строкой без явного обращения к методам файла:
>>> for line in open(‘script1.py’):# Использовать итератор файла
... print(line.upper(), end=’’) # Вызывает метод __next__,
... # перехватывает исключение StopIteration
IMPORT SYS
PRINT(SYS.PATH)
X = 2
PRINT(2 ** 33)
-----------------------------------------------------------------
Аналог, только используем метод readlines для загрузки содержимого файла в память в виде списка строк:
>>> for line in open(‘script1.py’).readlines():
... print(line.upper(), end=’’)
...
IMPORT SYS
PRINT SYS.PATH
X = 2
PRINT 2 ** 33
Проигрышный способ, так как он не экономит память.
-----------------------------------------------------------------
Возможность построчного чтения файлов с помощью цикла while:
>>> f = open(‘script1.py’)
>>> while True:
... line = f.readline()
... if not line: break
... print(line.upper(), end=’’)
...
...вывод тот же самый...
Однако такой вариант наверняка будет работать медленнее версии, основанной на использовании итератора в цикле for, потому что итераторы внутри интерпретатора выполняются со скоростью, присущей программам, написанным на языке C, тогда как версия на базе цикла while работает со скоростью интерпретации байт-кода виртуальной машиной Python.
-----------------------------------------------------------------
Выполнение итераций вручную: iter и next:
В Python 3.0 имеется встроенная функция next, которая автоматически вызывает метод __next__ объекта. Допустим, что у нас имеется итерируемый объект X, тогда вызов next(X) будет равносилен вызову X.__next__(), но выглядит намного проще.
Пример далее покажет функцию в действии:
>>> f = open(‘script1.py’)
>>> f.__next__() # Непосредственный вызов метода
‘import sys\n’
>>> f.__next__()
‘print(sys.path)\n’
Далее используем встроенную функцию next:
>>> f = open(‘script1.py’)
>>> next(f) # Встроенная функция next вызовет метод __next__
‘import sys\n’
>>> next(f)
‘print(sys.path)\n’
-----------------------------------------------------------------
Обработка списков:
>>> L = [1, 2, 3]
>>> I = iter(L) # Получить объект-итератор
>>> I.__next__() # Вызвать __next__, чтобы перейти к
# следующему элементу
1
>>> I.__next__()
2
>>> I.__next__()
3
>>> I.__next__()
Traceback (most recent call last):
...текст сообщения об ошибке опущен...
StopIteration
-----------------------------------------------------------------
Чтобы начать итерации по спискам, необходимо предварительно вызвать функцию iter:
>>> L = [1, 2, 3]
>>> iter(L) is L
False
>>> L.__next__()
AttributeError: ‘list’ object has no attribute ‘__next__’
>>> I = iter(L)
>>> I.__next__()
1
>>> next(I) # То же, что и вызов метода I.__next__()
2
-----------------------------------------------------------------
Автоматический и ручной способ организации итераций:
L = [1, 2, 3]
>>>
>>> for X in L: # Автоматический способ выполнения итераций
... print(X ** 2, end=’ ‘) # Получает итератор, вызывает __next__,
... # обрабатывает исключение
1 4 9
>>> I = iter(L) # Ручной способ итераций: имитация цикла for
>>> while True:
... try: # Инструкция try обрабатывает исключения
... X = next(I) # Или I.__next__
... except StopIteration:
... break
... print(X ** 2, end=’ ‘)
...
1 4 9
-----------------------------------------------------------------
Итераторы для словарей:
Инициализируем словарь:
>>> D = {‘a’:1, ‘b’:2, ‘c’:3}
>>> for key in D.keys():
... print(key, D[key])
...
a 1
c 3
b 2
Делаем итерацию:
>>> I = iter(D)
>>> next(I)
‘a’
>>> next(I)
‘c’
>>> next(I)
‘b’
>>> next(I)
Traceback (most recent call last):
...текст сообщения об ошибке опущен...
StopIteration
-----------------------------------------------------------------
Цикл for автоматически извлекает ключи, по одному из каждой итерации:
>>> for key in D:
... print(key, D[key])
...
a 1
c 3
b 2
Комментариев нет:
Отправить комментарий