2014-11-17 2 views
2

Я читал через некоторые старого кода шахты и наткнулся на эту линиюЕсть ли смысл использовать вложенные итераторы?

itertools.starmap(lambda x,y: x + (y,), 
        itertools.izip(itertools.repeat(some_tuple, 
                len(list_of_tuples)), 
           itertools.imap(lambda x: x[0], 
               list_of_tuples))) 

Чтобы было ясно, у меня есть некоторые list_of_tuples, из которого я хочу, чтобы получить первый элемент из каждого кортежа (itertools.imap), я есть еще один кортеж, который я хочу повторить (itertools.repeat), так что есть копия для каждого кортежа в list_of_tuples, а затем я хочу получить новые более длинные кортежи на основе элементов от list_of_tuples (itertools.starmap).

Например, предположим, что some_tuple = (1, 2, 3) и list_of_tuples = [(1, other_info), (5, other), (8, 12)]. Я хочу что-то вроде [(1, 2, 3, 1), (1, 2, 3, 5), (1, 2, 3, 8)]. Это не точный IO (он использует некоторые довольно нерелевантные и сложные классы), и мои фактические списки и кортежи очень большие.

Есть ли смысл встраивать итераторы? Мне кажется, что каждая функция из itertools должна будет перебирать итератор, который я дал ему, и хранить информацию от него где-то, что означает, что нет никакой пользы для размещения других итераторов внутри starmap. Я просто совершенно не прав? Как это работает?

+0

Если вы покажете нам, что ожидаемый ввод и вывод будет полезен для сопоставления ваших действий – Hackaholic

+0

Нет, по той простой причине, что он делает код слишком трудным для подражания. Keep It Simple –

+0

@gnibbler, так как это возможно, даже удаление его по-прежнему приводит нас к вложенным итераторам, поэтому, если удаление не изменит ответ, мне все еще интересно, есть ли смысл вложенности вообще – Dannnno

ответ

2

Там нет никаких оснований гнездовых итераторов. Использование переменных не оказывают заметное влияние на производительность/памяти:

first_items = itertools.imap(lambda x: x[0], list_of_tuples) 
repeated_tuple = itertools.repeat(some_tuple, len(list_of_tuples)) 
items = itertools.izip(repeated_tuple, first_items) 
result = itertools.starmap(lambda x,y: x + (y,), items) 

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

+0

Я думаю, что это действительно то, о чем я спрашивал. Я не был уверен, что, не вложив итераторы, я в конечном итоге сохранил больше вещей в памяти, чем хотел. Благодаря! – Dannnno

1

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

оказывается эквивалентным это выражение генератора:

(some_tuple + (y[0],) for y in list_of_tuples) 

Однако иногда itertools может иметь преимущество в производительности, особенно в CPython

+0

Таким образом, игнорируя пример, который я дал, что я вижу, не очень хороший, в общем случае вложение итераторов будет иметь какой-либо эффект, положительный или нет, на производительность программы? Или это то, что нужно было бы решить в каждом конкретном случае? – Dannnno

+2

@ Dannnno, вы должны предпочесть написать код наиболее читаемым способом. Если это окажется узким местом производительности, вы переписываете его, как вы думаете, быстрее. Держите легко читаемую версию в качестве документации. Вы можете написать свои модульные тесты для обеих версий, чтобы определить, было ли поведение случайно изменено в вашей более быстрой версии. –

Смежные вопросы