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

Первая итерация цикла "For"

Приветствия pyc-sires и py-ladies, Я хотел бы узнать, есть ли элегантный pythonic способ выполнения некоторой функции на первой итерации цикла. Единственная возможность, о которой я могу думать, это:

first = True
for member in something.get():
    if first:
        root.copy(member)
        first = False
    else:
        somewhereElse.copy(member)
    foo(member)
4b9b3361

Ответ 1

У вас есть несколько вариантов дизайна шаблона Head-Tail.

seq= something.get()
root.copy( seq[0] )
foo( seq[0] )
for member in seq[1:]:
    somewhereElse.copy(member)
    foo( member )

Или это

seq_iter= iter( something.get() )
head = seq_iter.next()
root.copy( head )
foo( head )
for member in seq_iter:
    somewhereElse.copy( member )
    foo( member )

Люди скулят, что это как-то не "СУХОЙ", потому что "избыточный код foo (member)". Это смехотворное требование. Если это так, то все функции можно использовать только один раз. Какой смысл определять функцию, если у вас есть только одна ссылка?

Ответ 2

Что-то вроде этого должно работать.

for i, member in enumerate(something.get()):
    if i == 0:
         # Do thing
    # Code for everything

Однако я бы настоятельно рекомендовал подумать о вашем коде, чтобы увидеть, действительно ли вам нужно это делать, потому что это своего рода "грязный". Лучше было бы получить элемент, который требует специальной обработки спереди, а затем выполнять регулярную обработку для всех остальных в цикле.

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

Ответ 3

как насчет:

my_array = something.get()
for member in my_array:
    if my_array.index(member) == 0:
        root.copy(member)
    else:
        somewhereElse.copy(member)
    foo(member)

или возможно:

for index, member in enumerate(something.get()):
    if index == 0:
        root.copy(member)
    else:
        somewhereElse.copy(member)
    foo(member)

Документация индексный метод.

Ответ 4

Я думаю, что это довольно элегантно, но, возможно, слишком запутанно для того, что он делает...

from itertools import chain, repeat, izip
for place, member in izip(chain([root], repeat(somewhereElse)), something.get()):
    place.copy(member)
    foo(member)

Ответ 5

Это работает:

for number, member in enumerate(something.get()):
    if not number:
        root.copy(member)
    else:
        somewhereElse.copy(member)
    foo(member)

В большинстве случаев я предлагаю просто перебирать whatever[1:] и делать корневую вещь вне цикла; что обычно более читаемо. Разумеется, зависит от вашего прецедента.

Ответ 6

Если something.get() итерирует что-то, вы можете сделать это также следующим образом:

root.copy(something.get())

for member in something.get():
  #  the rest of the loop

Ответ 7

Здесь я могу прийти с питонической идиомой, которая может выглядеть "pertty". Хотя, скорее всего, я бы использовал форму, которую вы предложили, задав вопрос, просто чтобы код оставался более очевидным, хотя и менее элегантным.

def copy_iter():
    yield root.copy
    while True:
        yield somewhereElse.copy

for member, copy in zip(something.get(), copy_iter()):
    copy(member)
    foo(member)

(извините - первый, который я опубликовал, до редактирования, форма не сработала, я забыл фактически получить итератор для объекта "copy" )

Ответ 8

Как насчет использования iter и потребления первого элемента?

Изменить: Возвращаясь к вопросу о OP, есть общая операция, которую вы хотите выполнить для всех элементов, а затем одну операцию, которую вы хотите выполнить для первого элемента, а другая - на остальное.

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

def common(item):
    print "common (x**2):", item**2

def wrap_common(func):
    """Wraps `func` with a common operation"""
    def wrapped(item):
        func(item)
        common(item)
    return wrapped

@wrap_common
def first(item):
    """Performed on first item"""
    print "first:", item+2

@wrap_common
def rest(item):
    """Performed on rest of items"""
    print "rest:", item+5

items = iter(range(5))
first(items.next())

for item in items:
    rest(item)

Вывод:

first: 2
common (x**2): 0
rest: 6
common (x**2): 1
rest: 7
common (x**2): 4
rest: 8
common (x**2): 9
rest: 9
common (x**2): 16

или вы можете сделать фрагмент:

first(items[0])
for item in items[1:]:
    rest(item)

Ответ 9

Я думаю, что первое решение S.Lott - лучшее, но есть другой выбор, если вы используете довольно недавний python ( >= 2.6, я думаю, поскольку izip_longest пока недоступен до этой версии), что позволяет делать разные вещи для первого элемента и последовательные, и могут быть легко модифицированы для выполнения отдельных операций для 1-го, 2-го, 3-го элементов... также.

from itertools import izip_longest

seq = [1, 2, 3, 4, 5]

def headfunc(value):
    # do something
    print "1st value: %s" % value

def tailfunc(value):
    # do something else
    print "this is another value: %s" % value

def foo(value):
    print "perform this at ANY iteration."

for member, func in izip_longest(seq, [headfunc], fillvalue=tailfunc):
    func(member)
    foo(member)

Ответ 10

Вы не можете сделать root.copy(something.get()) перед циклом?

EDIT: Извините, я пропустил второй бит. Но вы получаете общую идею. В противном случае перечислите и проверьте 0?

EDIT2: Хорошо, избавился от глупой второй идеи.

Ответ 11

Я не знаю Python, но я использую почти точный шаблон вашего примера.
То, что я делаю, также делает условие if наиболее частым, поэтому обычно проверяйте if( first == false )
Зачем? для длинных циклов сначала будет истинно только один раз и будет ложным все другие времена, что означает, что во всех циклах, кроме первого, программа будет проверять состояние и перейти к части else.
Проверяя, что первое было ложным, будет только один переход к части else. Я не знаю, добавляет ли это эффективность вообще, но я все равно делаю это, просто чтобы быть в покое с моим внутренним ботаником.

PS: Да, я знаю, что при входе в часть if он также должен перепрыгивать через else, чтобы продолжить выполнение, поэтому, вероятно, мой способ сделать это бесполезен, но он чувствует себя хорошо.: D

Ответ 12

Ваш вопрос противоречив. Вы говорите: "делайте только что-то на первой итерации", когда на самом деле вы говорите что-то другое на первых и последующих итерациях. Вот как я попытался бы это сделать:

copyfn = root.copy
for member in something.get():
    copyfn(member)
    foo(member)
    copyfn = somewhereElse.copy