“For”循环第一次迭代

时间:2009-12-18 11:03:27

标签: python algorithm iteration

我想询问是否有一种优雅的pythonic方式在第一次循环迭代中执行某些函数。 我能想到的唯一可能性是:

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

13 个答案:

答案 0 :(得分:60)

这样的事情应该有效。

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

但是,我强烈建议您考虑一下代码,看看是否真的必须这样做,因为它有点“脏”。更好的方法是先获取需要特殊处理的元素,然后对循环中的所有其他元素进行常规处理。

我可以看到不这样做的唯一原因是你可以从生成器表达式获得一个大的列表(你不想在前面获取因为它不适合内存),或类似情况。

答案 1 :(得分:36)

您可以选择 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(成员)”代码。这是一个荒谬的说法。如果这是真的那么所有函数只能使用一次。如果你只能有一个参考,那么定义一个函数有什么意义呢?

答案 2 :(得分:11)

怎么样:

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)

index-method的文档。

答案 3 :(得分:6)

我觉得这很优雅,但也许它太复杂了......

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

答案 4 :(得分:5)

在这里,我可以找到一个看起来“有点”的Pythonic成语。虽然,我很可能会在提出问题时使用您建议的表单,但代码仍然更加明显,尽管不那么优雅。

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'对象的迭代器)

答案 5 :(得分:4)

这有效:

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

在大多数情况下,我建议只是迭代whatever[1:]并在循环之外做根源;这通常更具可读性。当然,取决于你的用例。

答案 6 :(得分:3)

如果something.get()迭代某些东西,你也可以按如下方式进行:

root.copy(something.get())

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

答案 7 :(得分:3)

如何使用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)

答案 8 :(得分:3)

我认为第一个S.Lott解决方案是最好的,但如果您使用的是最新的python(&gt; = 2.6我认为,因为izip_longest在该版本之前似乎不可用)还有其他选择第一个元素和连续元素的不同内容,可以很容易地修改为第一,第二,第三元素的不同操作......也是。

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)

答案 9 :(得分:1)

你不能在循环之前做root.copy(something.get())吗?

编辑:抱歉,我错过了第二位。但是你得到了一般的想法。否则,枚举并检查0

EDIT2:好的,摆脱了愚蠢的第二个想法。

答案 10 :(得分:1)

我不懂Python,但我几乎使用了你的例子的确切模式 我所做的也是使if条件最频繁,所以通常检查if( first == false )
为什么?对于长循环,首先只有一次是真的,并且在所有其他时间都是假的,这意味着在所有循环中但是第一次,程序将检查条件并跳转到else部分。
通过检查第一个是否为假,只有一个跳转到else部分。我真的不知道这是否会增加效率,但无论如何我都会这样做,只是为了与内心的书呆子保持和平。

PS:是的,我知道当进入if部分时,它还必须跳过其他部分才能继续执行,所以我的做法可能没用,但感觉还不错。 :d

答案 11 :(得分:0)

你的问题是矛盾的。你说&#34;只在第一次迭代时做某事&#34;,实际上你说的是在第一次/后续迭代时做一些不同的事情。这是我尝试的方式:

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

答案 12 :(得分:0)

这是对我有用的

    dup_count = 0
    for x in reversed(dup_list):
        dup_count += 1
        if dup_count == 1:
            print("First obj {}: {}".format(dup_count,x))
        else:
            print("Object # {}:  {}".format( dup_count,x  ))