itertools или рукописный генератор - что предпочтительнее?

У меня есть несколько генераторов Python, которые я хочу объединить в новый генератор. Я могу легко сделать это с помощью написанного от руки генератора, используя связку операторов yield .

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

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

EDIT

Чтобы проиллюстрировать мою проблему, вот (игрушечный) пример : Пусть a и b будут двумя итерациями одинаковой длины (входные данные). Элементы a состоят из целых чисел, элементы b сами являются итерациями, отдельные элементы которых являются строками. Выходные данные должны соответствовать выходным данным следующей функции генератора:

from itertools import *
def generator(a, b):
    first = True
    for i, s in izip(a, b):
        if first:
            yield "First line"
            first = False
        else:
            yield "Some later line"
        if i == 0:
            yield "The parameter vanishes."
        else:
            yield "The parameter is:"
            yield i
        yield "The strings are:"
        comma = False
        for t in s:
            if comma:
                yield ','
            else:
                comma = True
            yield t

Если я запишу ту же программу в функциональном стиле, используя выражения генератора и Пусть a и b будут двумя итерациями одинаковой длины (входные данные). Элементы a состоят из целых чисел, элементы b сами являются итерациями, отдельные элементы которых являются строками. Выходные данные должны соответствовать выходным данным следующей функции генератора:

from itertools import *
def generator(a, b):
    first = True
    for i, s in izip(a, b):
        if first:
            yield "First line"
            first = False
        else:
            yield "Some later line"
        if i == 0:
            yield "The parameter vanishes."
        else:
            yield "The parameter is:"
            yield i
        yield "The strings are:"
        comma = False
        for t in s:
            if comma:
                yield ','
            else:
                comma = True
            yield t

Если я запишу ту же программу в функциональном стиле, используя выражения генератора и Пусть a и b будут двумя итерациями одинаковой длины (входные данные). Элементы a состоят из целых чисел, элементы b сами являются итерациями, отдельные элементы которых являются строками. Выходные данные должны соответствовать выходным данным следующей функции генератора:

from itertools import *
def generator(a, b):
    first = True
    for i, s in izip(a, b):
        if first:
            yield "First line"
            first = False
        else:
            yield "Some later line"
        if i == 0:
            yield "The parameter vanishes."
        else:
            yield "The parameter is:"
            yield i
        yield "The strings are:"
        comma = False
        for t in s:
            if comma:
                yield ','
            else:
                comma = True
            yield t

Если я запишу ту же программу в функциональном стиле, используя выражения генератора и itertools , я получаю что-то вроде:

from itertools import *
def generator2(a, b):
    return (z for i, s, c in izip(a, b, count())
            for y in (("First line" if c == 0 else "Some later line",),
                      ("The parameter vanishes.",) if i == 0
                      else ("The parameter is:", i),
                      ("The strings are:",),
                      islice((x for t in s for x in (',', t)), 1, None))
            for z in y)

ПРИМЕР

>>> a = (1, 0, 2), ("ab", "cd", "ef")
>>> print([x for x in generator(a, b)])
['First line', 'The parameter is:', 1, 'The strings are:', 'a', ',', 'b', 'Some later line', 'The parameter vanishes.', 'The strings are:', 'c', ',', 'd', 'Some later line', 'The parameter is:', 2, 'The strings are:', 'e', ',', 'f']
>>> print([x for x in generator2(a, b)])
['First line', 'The parameter is:', 1, 'The strings are:', 'a', ',', 'b', 'Some later line', 'The parameter vanishes.', 'The strings are:', 'c', ',', 'd', 'Some later line', 'The parameter is:', 2, 'The strings are:', 'e', ',', 'f']

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

PS: Я полагаю, что часть моей проблемы с функциональным решением заключается в том, что для минимизации количества ключевых слов в Python некоторые ключевые слова, такие как «for», «if» и «else» были переработаны для использования в выражениях, так что их размещение в выражении требует привыкания (порядок в выражении генератора z for x in a for y in x for z in y выглядит, по крайней мере, для меня, менее естественным, чем порядок в классическом для цикла: для x в a: для y в x: для z в y: вывести z ).

7
задан Marc 4 October 2010 в 07:45
поделиться