Заметки по Python (16): Генераторы и итераторы

Python Технологии Nuggets призывают к публикации
Заметки по Python (16): Генераторы и итераторы

Мало знаний, большой вызов! Эта статья участвует в "Необходимые знания для программистов«Творческая деятельность.

Привет всем, яодна чаша в неделю, передняя часть, которая не хочет быть пьяной (завернутой). Если написанной статье посчастливилось получить вашу благосклонность, мне очень повезло~

Строитель

Теперь список можно создать напрямую через генератор, но из-за ограничения памяти емкость списка должна быть ограничена.Если нам нужен список, содержащий сотни элементов, но каждый раз обращаются только к нескольким из них, Если остальные элементы не используются, это пустая трата памяти.

В настоящее времяСтроитель(Generator) играет роль, он непрерывно генерирует новые данные по определенному алгоритму до тех пор, пока не будет выполнено заданное условие.

Есть несколько способов получить генеративное выражение:

  1. Генератор получается путем понимания списка.Пример кода выглядит следующим образом:

    g = (x for x in range(10))  # 将列表生成列的[]改变成为()
    # 打印其类型
    print(type(g))  # <class 'generator'>
    # 调用其元素
    print(g.__next__())  # 0
    print(g.__next__())  # 1
    print(g.__next__())  # 2
    print(g.__next__())  # 3
    print(g.__next__())  # 4
    # 使用.__next__的方式调用
    print(next(g))  # 5
    print(next(g))  # 6
    print(next(g))  # 7
    print(next(g))  # 8
    print(next(g))  # 9
    # 使用next()的方法调用
    print(next(g))  # 当数据调用不到时会报出错误 StopIteration
    

    Сколько вызовов необходимо, а те, которые не вызываются, не будут генерироваться и не будут занимать место в памяти.Вы можете использовать структуру цикла для вызова по мере необходимости

    g = (x for x in range(10))  # 将列表生成列的[]改变成为()
    skip = True  # 判断条件
    count = 0  # 调用次数
    while skip:
        count += 1  # 循环一次+1
        print(next(g))
        if count > 9:
            break  # 跳出循环
    
  2. использовать функциюyieldключевое слово для завершения генератора, который генерируетПоследовательность ФибоначчиПервые 20 чисел, пример кода выглядит следующим образом:

    def fun(length):
        a, b = 0, 1
        for _ in range(length):
            a, b = b, a + b
            yield a
    
    
    fib = fun(20)
    print(type(fib))  # <class 'generator'>  # 打印类型
    count = 0
    while count < 20:
        # 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765
        print(next(fib), "", end="")
        count += 1
    

    Процесс выглядит следующим образом:

    В процессе выполнения, когда встретится ключевое слово yield, выполнение будет приостановлено, и следующий вызов продолжится с последней приостановленной позиции, поскольку это оператор цикла, все сразу перейдет к оператору for.

    Если вы вызываете yield и вам нужно передать ему значение, вам нужно использовать.send()метод. Пример кода выглядит следующим образом:

    def fun(num):
        n = 0
        for i in range(num + 1):
            n += i
            ret = yield n
            print(f"这是+到{ret}的第{i + 1} 次")
    
    
    g = fun(3)
    print(g.send(None))
    print(g.send('3'))
    print(g.send('3'))
    print(g.send('3'))
    '''
    ---输出结果---
    0
    这是+到 3 的第 1 次
    1
    这是+到 3 的第 2 次
    3
    这是+到 3 的第 3 次
    6
    '''
    

    sendДобавление может сделать генератор более гибким, но следует отметить, что первый вызов генератораsend()метод, параметры могут быть толькоNone, иначе будет выброшено исключение. Конечно, вы также можете позвонитьsend()метод вызывается один раз передnext()метод, цель состоит в том, чтобы позволить генератору войти первымyieldвыражение.

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

К итерируемым объектам относятся генераторы, кортежи, списки, наборы, словари, строки и т. д.

пройти черезcollectionsизIterableсвязывание функцийisinstance(object, classinfo)чтобы определить, когда объект не является итерируемым объектом

Итерация — это способ доступа к элементам коллекции. Итератор — это объект, который запоминает, где проходить. Доступ к объектам Iterator осуществляется с первого элемента коллекции до тех пор, пока не будут доступны все элементы. Итераторы могут идти только вперед, а не назад. Генераторы также являются итераторами.

возможноnext ()Объекты, которые вызывает функция и продолжает возвращать следующее значение, называются итераторами:Iterator,можно использоватьisinstance()определить, является ли объектIteratorОбъект:

Уведомление: Итерируемый объект не обязательно является генератором, но генератор должен быть итерируемым.

Преобразование кортежей, списков, наборов, словарей, строк и т. д.IterableстатьIteratorможно использоватьiter()функция

IterableиIterator****РазницадаIterableможно использовать какforобщий термин для циклических объектов; иIteratorобъект должен бытьnext()Вызов функции будет продолжать возвращать следующие данные до тех пор, пока не будет данных для выбрасывания.StopIterationошибка, и ее длина не будет известна до тех пор, поэтомуIteratorВычисление ленивое, толькоnext()Функция вызывает его, чтобы вернуть результат,IteratorОн может даже представлять бесконечный поток данных, например, все натуральные числа.

from collections.abc import Iterable, Iterator
a = [1, 2, 3]
b = {1, 2, 3}
c = (1, 2, 3)
d = "123"
e = 123
f = (x for x in range(5))
# 打印数据类型
print(type(a))  # <class 'list'>
print(type(b))  # <class 'set'>
print(type(c))  # <class 'tuple'>
print(type(d))  # <class 'str'>
print(type(e))  # <class 'int'>
print(type(f))  # <class 'generator'>
print("-" * 20)

# 打印是否为可迭代对象
print(isinstance(a, Iterable))  # True
print(isinstance(b, Iterable))  # True
print(isinstance(c, Iterable))  # True
print(isinstance(d, Iterable))  # True
print(isinstance(e, Iterable))  # False
print(isinstance(f, Iterable))  # True
print("-" * 20)
# 除了字符串都是可迭代对象

# 打印是否是迭代器
print(isinstance(a, Iterator))  # False
print(isinstance(b, Iterator))  # False
print(isinstance(c, Iterator))  # False
print(isinstance(d, Iterator))  # False
print(isinstance(f, Iterator))  # True
# 只有f(生成器)是迭代器
print("-" * 20)


# 通过iter()将可迭代转换为迭代器
print(isinstance(iter(a), Iterator))  # True
print(isinstance(iter(b), Iterator))  # True
print(isinstance(iter(c), Iterator))  # True
print(isinstance(iter(d), Iterator))  # True