Python

Search for '{{search_term}}'

Функция обратного вызова (callback) или итератор в Python

CMOS is the Code-Maven Open Source podcast that also includes video interviews. Subscribe to this feed RSS feed with your Podcast listener app or via iTunes iTunes.

Раньше мы видели, как функции обратного вызова (колбеки) могут быть лучше простых функций, но есть и другие варианты. Мы можем создать, вероятно, неограниченный итератор, который будет обходить элементы нашей последовательности, делая код еще более понятным, чем даже решение с колбеками.

Решение с колбеком

Просто для напоминания - вот наше решение с колбеком. У нас есть функция fibonacci, которая проходит элементы последовательности, и для каждого элемента вызывает переданную функцию check_17.

examples/python/fibonacci_function_callback.py

#!/usr/bin/env python
from __future__ import print_function

def fibonacci(cb):
    values = []
    while(True):
        if len(values) < 2:
            values.append(1)
        else:
            values = [values[-1], values[-1] + values[-2]]

        r = cb(values[-1])
        if (r[0]):
            return(r[1])

def check_17(v):
    if v % 17 == 0:
        return (True, v)

    if v > 10000:
        return (True, None)

    return (False,)


if __name__ == '__main__':
    res = fibonacci(check_17)
    if (res != None):
        print(res)

Тот факт, что мы должны иметь возможность передать функции fibonacci сигнал, когда остановиться, делает наш код несколько сложнее, чем мы надеялись. Мы должны возвращать массив, в котором первый элемент выполняет роль индикатора (True/False).

Создание Fibonacci-итератора

Давайте сделаем все наоборот и позволим пользователю вернуть контроль над циклом. Мы создаем класс Fibonacci, который будет итерабельным вследствие добавления метода __iter__, который просто возвращает объект, и метода next (В Python 3, думаю, это будет __next__), который возвращает следующий элемент.

Внутри объект содержит текущее состояние итерации. В нашем случае это значит, что он должен содержать последние два элемента последовательности.

examples/python/fibonacci_iterator.py

#!/usr/bin/env python
from __future__ import print_function

class Fibonacci(object):
    def __init__(self):
        self.values = []

    def __iter__(self):
        return self

    def next(self):
        if len(self.values) < 2:
            self.values.append(1)
        else:
            self.values = [self.values[-1], self.values[-1] + self.values[-2]]
        return self.values[-1]

for f in Fibonacci():
    if f % 17 == 0:
        print(f)
        break
    if f > 10000:
        break

Вызов fib = Fibonacci() создаст объект итератора, который мы можем использовать в конструкции for in для перебора элементов. Поскольку это неограниченный итератор, то есть, он не имеет конца, мы должны быть уверены, что есть какой-то код внутри цикла for, который его как-то остановит.

Решение выглядит проще, чем вариант с колбеками.

Savenkova Natalya
Переводчик
Savenkova Natalya
Gabor Szabo
Автор
Gabor Szabo

Comments