Рубрики
Без рубрики

Итераторы и генераторы

5. Итераторы и генераторы 5.1. Итераторы мы используем для выписки для петли по списку. >>… Теги с Python, начинающими, CodeNewie, написание.

5. Итераторы и генераторы 5.1. Итераторы Мы используем для Заявление для зацикливания по списку.

>>> for i in [1, 2, 3, 4]:
...     print(i)
...
1
2
3
4

Если мы используем его со строкой, она петлями по его символам.

>>> for c in "python":
...     print(c)
...
p
y
t
h
o
n

Если мы используем его с помощью словаря, он петли по его ключам.

>>> for k in {"x": 1, "y": 2}:
...     print(k)
...
y
x

Если мы используем его с файлом, оно петли по линиям файла.

>>> for line in open("a.txt"):
...     print(line, end="")
...
first line
second line

Таким образом, существует много типов объектов, которые можно использовать с A для цикла. Они называются ИТЕРАЛНЫЕ объекты Отказ

Есть много функций, которые потребляют эти поематы.

>>> ",".join(["a", "b", "c"])
'a,b,c'
>>> ",".join({"x": 1, "y": 2})
'y,x'
>>> list("python")
['p', 'y', 't', 'h', 'o', 'n']
>>> list({"x": 1, "y": 2})
['y', 'x']

5.1.1. Протокол итерации Встроенная функция ИТЕР берет счет и возвращает итератор.

>>> x = iter([1, 2, 3])
>>> x

>>> next(x)
1
>>> next(x)
2
>>> next(x)
3
>>> next(x)
Traceback (most recent call last):
  File "", line 1, in 
StopIteration

Каждый раз, когда мы называем Следующий Метод на итераторе дает нам следующий элемент. Если больше элементов больше нет, он поднимает Заставка Отказ

Итераторы реализуются как классы. Вот итератор, который работает как встроенный Диапазон функция.

class yrange:
    def __init__(self, n):
        self.i = 0
        self.n = n

    def __iter__(self):
        return self

    def __next__(self):
        if self.i < self.n:
            i = self.i
            self.i += 1
            return i
        else:
            raise StopIteration()

__er____ Метод – это то, что делает объект, который является рейтируемым. За кулисами функция ITER звонит __er____ Способ на данном объекте.

Возвращаемое значение __er____ это итератор. У него должно быть __Next__ Метод и повышение Заставка Когда больше элементов больше нет.

Давайте попробуем это:

>>> y = yrange(3)
>>> next(y)
0
>>> next(y)
1
>>> next(y)
2
>>> next(y)
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 14, in __next__
StopIteration

Многие встроенные функции принимают итераторы как аргументы.

>>> list(yrange(5))
[0, 1, 2, 3, 4]
>>> sum(yrange(5))
10

В приведенном выше случае как итеративный и итератор – это тот же объект. Обратите внимание, что __er____ Метод вернул себя. Это не должно быть так, всегда.

class zrange:
    def __init__(self, n):
        self.n = n

    def __iter__(self):
        return zrange_iter(self.n)

class zrange_iter:
    def __init__(self, n):
        self.i = 0
        self.n = n

    def __iter__(self):
        # Iterators are iterables too.
        # Adding this functions to make them so.
        return self

    def __next__(self):
        if self.i < self.n:
            i = self.i
            self.i += 1
            return i
        else:
            raise StopIteration()

Если и итератор и итератор один и тот же объект, он потребляется в одной итерации.

>>> y = yrange(5)
>>> list(y)
[0, 1, 2, 3, 4]
>>> list(y)
[]
>>> z = zrange(5)
>>> list(z)
[0, 1, 2, 3, 4]
>>> list(z)
[0, 1, 2, 3, 4]

Проблема 1: Написать класс iTerator refort_iter , это принимает список и итасит его из обратного направления.::

>>> it = reverse_iter([1, 2, 3, 4])
>>> next(it)
4
>>> next(it)
3
>>> next(it)
2
>>> next(it)
1
>>> next(it)
Traceback (most recent call last):
  File "", line 1, in 
StopIteration

5.2. Генераторы Генераторы упрощают создание итераторов. Генератор представляет собой функцию, которая производит последовательность результатов вместо одного значения.

def yrange(n):
    i = 0
    while i < n:
        yield i
        i += 1

Каждый раз доходность Заявление выполняется. Функция генерирует новое значение.

>>> y = yrange(3)
>>> y

>>> next(y)
0
>>> next(y)
1
>>> next(y)
2
>>> next(y)
Traceback (most recent call last):
  File "", line 1, in 
StopIteration

Таким образом, генератор также является итератор. Вам не нужно беспокоиться о протоколе итераторов.

Слово «генератор» сбивается смущенным, чтобы означать как функцию, которая генерирует, и что она генерирует. В этой главе я буду использовать слово «генератор», чтобы означать, что Genearted Object и «Функция генератора» означает функцию, которая ее генерирует.

Можете ли вы подумать о том, как он работает внутри

Когда функция генератора вызывается, она возвращает объект генератора, даже не начал выполнения функции. Когда Следующий Метод впервые вызывается, функция начинает выполнять, пока не достигнет доходность утверждение. Допустимая стоимость возвращается Следующий вызов.

В следующем примере демонстрирует взаимодействие между доходность и позвонить в __Next__ Метод на объекте генератора.

>>> def foo():
...     print("begin")
...     for i in range(3):
...         print("before yield", i)
...         yield i
...         print("after yield", i)
...     print("end")
...
>>> f = foo()
>>> next(f)
begin
before yield 0
0
>>> next(f)
after yield 0
before yield 1
1
>>> next(f)
after yield 1
before yield 2
2
>>> next(f)
after yield 2
end
Traceback (most recent call last):
  File "", line 1, in 
StopIteration
>>>

Давайте посмотрим пример:

def integers():
    """Infinite sequence of integers."""
    i = 1
    while True:
        yield i
        i = i + 1

def squares():
    for i in integers():
        yield i * i

def take(n, seq):
    """Returns first n values from the given sequence."""
    seq = iter(seq)
    result = []
    try:
        for i in range(n):
            result.append(next(seq))
    except StopIteration:
        pass
    return result

print(take(5, squares())) # prints [1, 4, 9, 16, 25]

5.3. Разращивания генератора Выражения генератора являются версией генератора. Они похожи на потенциал списка, но возвращает генератор обратно вместо списка.

>>> a = (x*x for x in range(10))
>>> a
 at 0x401f08>
>>> sum(a)
285

Мы можем использовать выражения генератора в качестве аргументов различным функциям, которые потребляют итераторы.

>>> sum((x*x for x in range(10)))
285

Когда имеется только один аргумент для вызывающей функции, скобки вокруг выражения генератора могут быть опущены.

>>> sum(x*x for x in range(10))
285

Еще один веселый пример:

Позвольте сказать, что мы хотим найти первые 10 (или какие-либо n) пифагореевые тройки. Триплет (x, y, z) называется Pythogorian Triblet, если x * x + y * y * z Отказ

Легко решить эту проблему, если мы знаем до какого значения Z для проверки. Но мы хотим найти первые N Pythagorean Triples.

>>> pyt = ((x, y, z) for z in integers() for y in range(1, z) for x in range(1, y) if x*x + y*y == z*z)
>>> take(10, pyt)
[(3, 4, 5), (6, 8, 10), (5, 12, 13), (9, 12, 15), (8, 15, 17), (12, 16, 20), (15, 20, 25), (7, 24, 25), (10, 24, 26), (20, 21, 29)]

5.3.1. Пример: Чтение нескольких файлов Позвольте сказать, что мы хотим написать программу, которая принимает список файлов в качестве аргументов и печатает содержимое всех этих файлов, таких как кот Команда в Unix.

Традиционный способ реализации это:

def cat(filenames):
    for f in filenames:
        for line in open(f):
            print(line, end="")

Теперь, давайте скажем, мы хотим распечатать только строку, которая имеет определенную подстроку, как Греп Команда в Unix.

def grep(pattern, filenames):
    for f in filenames:
        for line in open(f):
            if pattern in line:
                print(line, end="")

Обе эти программы имеют много кода общего. Трудно переместить общую части к функции. Но с генераторами позволяет это сделать.

def readfiles(filenames):
    for f in filenames:
        for line in open(f):
            yield line

def grep(pattern, lines):
    return (line for line in lines if pattern in line)

def printlines(lines):
    for line in lines:
        print(line, end="")

def main(pattern, filenames):
    lines = readfiles(filenames)
    lines = grep(pattern, lines)
    printlines(lines)

Код намного проще сейчас с каждой функцией делает одну маленькую вещь. Мы можем перемещать все эти функции в отдельный модуль и повторно использовать его в других программах.

Проблема 2: Напишите программу, которая принимает одну или несколько файлов в качестве аргументов и печатает все линии, которые находятся длиннее 40 символов.

Проблема 3: Написать функцию FindFiles Это рекурсивно спускается к дереву каталога для указанного каталога и генерирует пути всех файлов в дереве.

Проблема 4: Напишите функцию для вычисления количества файлов Python (расширение .py) в указанном каталоге рекурсивно.

Проблема 5: Напишите функцию, чтобы вычислить общее количество строк кода во всех файлах Python в указанном каталоге рекурсивно.

Проблема 6: Напишите функцию, чтобы вычислить общее количество строк кода, игнорирование пустых и комментариев линий, во всех файлах Python в указанном каталоге рекурсивно.

Проблема 7: Написать программу Split.py , это принимает целое число N и имя файла в качестве аргументов командной строки и разделяет файл в несколько небольших файлов с каждым имеющим N строки.

5.4. Itertools Модуль ITERTOOLS в стандартной библиотеке предоставляет много интересных инструментов для работы с итераторами.

Давайте посмотрим на некоторые интересные функции.

цепь – цепи многоетаторы вместе.

>>> it1 = iter([1, 2, 3])
>>> it2 = iter([4, 5, 6])
>>> itertools.chain(it1, it2)
[1, 2, 3, 4, 5, 6]

Izip – ИС

>>> for x, y in itertools.izip(["a", "b", "c"], [1, 2, 3]):
...     print(x, y)
...
a 1
b 2
c 3

Проблема 8: Написать функцию заглядывать , это требует итератора в качестве аргумента и возвращает первый элемент и эквивалентный итератор.

>>> it = iter(range(5))
>>> x, it1 = peep(it)
>>> print(x, list(it1))
0 [0, 1, 2, 3, 4]

Проблема 9: Встроенная функция перечисления принимает итерателя и возвращает итератор по пару (индекс, значение) для каждого значения в источнике.

>>> list(enumerate(["a", "b", "c"])
[(0, "a"), (1, "b"), (2, "c")]
>>> for i, c in enumerate(["a", "b", "c"]):
...     print(i, c)
...
0 a
1 b
2 c

Оригинал: “https://dev.to/estherwavinya/iterators-generators-1ghk”