Подтвердить что ты не робот

Где лучше всего использовать урожай в Python?

Я знаю, как работает yield. Я знаю перестановку, думаю, это просто математическая простота.

Но какая yield истинная сила? Когда я должен его использовать? Простой и хороший пример лучше.

4b9b3361

Ответ 1

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

Например, у меня есть python script, который анализирует большой список файлов CSV, и я хочу вернуть каждую строку, которая будет обрабатываться в другой функции. Я не хочу хранить мегабайты данных в памяти все сразу, поэтому я yield каждую строку в структуре данных python. Таким образом, функция для получения строк из файла может выглядеть примерно так:

def get_lines(files):
    for f in files:
        for line in f:
            #preprocess line
            yield line

Затем я могу использовать тот же синтаксис, что и со списками, для доступа к выходному сигналу этой функции:

for line in get_lines(files):
    #process line

но я сохраняю много использования памяти.

Ответ 2

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

>>> def get_odd_numbers(i):
...     return range(1, i, 2)
... 
>>> def yield_odd_numbers(i):
...     for x in range(1, i, 2):
...             yield x
... 
>>> foo = get_odd_numbers(10)
>>> bar = yield_odd_numbers(10)
>>> foo
[1, 3, 5, 7, 9]
>>> bar
<generator object yield_odd_numbers at 0x1029c6f50>
>>> bar.next()
1
>>> bar.next()
3
>>> bar.next()
5

Как вы можете видеть, в первом случае foo хранит сразу весь список в памяти. Это не большое дело для списка с 5 элементами, но что, если вы хотите список из 5 миллионов? Мало того, что это огромный eater памяти, он также требует много времени, чтобы построить в то время, когда функция вызывается. Во втором случае bar просто дает вам генератор. Генератор является итерируемым, что означает, что вы можете использовать его в цикле for и т.д., Но каждое значение может быть доступно только один раз. Все значения также не сохраняются в памяти одновременно; объект-генератор "запоминает", где он был в цикле в последний раз, когда вы его назвали, - таким образом, если вы используете итерируемый (скажем) счет до 50 миллиардов, вам не нужно считать до 50 миллиардов всех сразу и хранить 50 миллиардов номеров для подсчета. Опять же, это довольно надуманный пример, вы, вероятно, использовали бы itertools, если бы вы действительно хотели сосчитать до 50 миллиардов.:)

Это самый простой вариант использования генераторов. Как вы сказали, его можно использовать для написания эффективных перестановок, используя yield, чтобы проталкивать вещи через стек вызовов вместо использования какой-то переменной стека. Генераторы также могут использоваться для специализированного обхода дерева и всех других вещей.

Дальнейшее чтение:

Ответ 3

Другое использование - в сетевом клиенте. Используйте "yield" в функции генератора для циклического развертывания через несколько сокетов без сложности потоков.

Например, у меня был аппаратный тестовый клиент, которому необходимо было отправить R, G, B плоскости изображения в прошивку. Данные необходимо отправить в замок: красный, зеленый, синий, красный, зеленый, синий. Вместо того, чтобы порождать три потока, у меня был генератор, который читал из файла, закодировал буфер. Каждый буфер был "доходным buf". Конец файла, возвращаемая функция и у меня был конец итерации.

Мой клиентский код зациклился на трех функциях генератора, получив буферы до конца итерации.

Ответ 4

Я читаю структуры данных и алгоритмы в Python

Существует функция Фибоначчи, использующая выход. Я думаю, что это лучший момент для использования доходности.

def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a+b

вы можете использовать это как:

gen = fibonacci()
for i, f in enumerate(gen):
    print(i, f)
    if i >= 100: break

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