“为了”循环第一次迭代

发布于 2024-08-16 04:44:23 字数 253 浏览 4 评论 0原文

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

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

I would like to inquire if there is an elegant pythonic way of executing some function on the first loop iteration.
The only possibility I can think of is:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

山有枢 2024-08-23 04:44:23

像这样的东西应该有效。

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

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

我认为不这样做的唯一原因是为了从生成器表达式中获得一个大列表(您不想预先获取它,因为它不适合内存),或类似的情况。

Something like this should work.

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

However, I would strongly recommend thinking about your code to see if you really have to do it this way, because it's sort of "dirty". Better would be to fetch the element that needs special handling up front, then do regular handling for all the others in the loop.

The only reason I could see for not doing it this way is for a big list you'd be getting from a generator expression (which you wouldn't want to fetch up front because it wouldn't fit in memory), or similar situations.

蓝色星空 2024-08-23 04:44:23

对于头尾设计模式,您有多种选择。

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)”代码。这是一个荒谬的说法。如果这是真的,那么所有功能只能使用一次。如果只能有一个引用,那么定义函数还有什么意义呢?

You have several choices for the Head-Tail design pattern.

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

Or this

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

People whine that this is somehow not "DRY" because the "redundant foo(member)" code. That's a ridiculous claim. If that was true then all functions could only be used once. What's the point of defining a function if you can only have one reference?

南七夏 2024-08-23 04:44:23

怎么样:

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)

索引方法的文档。

how about:

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

or maybe:

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

Documentation of index-method.

祁梦 2024-08-23 04:44:23

这是可行的:

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

不过,在大多数情况下,我建议只迭代 whatever[1:] 并在循环外执行根本操作;这通常更具可读性。当然,取决于您的用例。

This works:

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

In most cases, though, I'd suggest just iterating over whatever[1:] and doing the root thing outside the loop; that's usually more readable. Depends on your use case, of course.

禾厶谷欠 2024-08-23 04:44:23

在这里,我可以使用一个看起来“pertty”的 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)

(抱歉 - 我发布的第一个在编辑之前,表单无法工作,我忘记了实际获取“复制”对象的迭代器)

Here, I could come with a Pythonic idiom that can look "pertty". Although, most likely I'd use the form you suggested in asking the question, just for the code to remain more obvious, though less elegant.

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

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

(sorry - the first I posted, before editing, form would not work, I had forgotten to actually get an iterator for the 'copy' object)

戏蝶舞 2024-08-23 04:44:23

我认为这非常优雅,但对于它的作用来说可能太复杂了......

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

I think this is quite elegant, but maybe too convoluted for what it does...

from itertools import chain, repeat, izip
for place, member in izip(chain([root], repeat(somewhereElse)), something.get()):
    place.copy(member)
    foo(member)
无名指的心愿 2024-08-23 04:44:23

如果something.get()迭代某些东西,你也可以这样做:

root.copy(something.get())

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

If something.get() iterates over something, you can do it also as follows:

root.copy(something.get())

for member in something.get():
  #  the rest of the loop
≈。彩虹 2024-08-23 04:44:23

我认为第一个 S.Lott 解决方案是最好的,但是如果您使用的是最近的 python (>= 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)

I think the first S.Lott solution is the best, but there's another choice if you're using a pretty recent python (>= 2.6 I think, since izip_longest doesn't seem available before that version) that lets doing different things for the first element and successive one, and can be easily modified to do distinct operations for 1st, 2nd, 3rd element... as well.

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)
烟花易冷人易散 2024-08-23 04:44:23

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

How about using iter, and consuming the first element?

Edit: Going back on the OP's question, there is a common operation that you want to perform on all elements, and then one operation you want to perform on the first element, and another on the rest.

If it's just a single function call, I'd say just write it twice. It won't end the world. If it's more involved, you can use a decorator to wrap your "first" function and "rest" function with a common operation.

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)

Output:

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

or you could do a slice:

first(items[0])
for item in items[1:]:
    rest(item)
但可醉心 2024-08-23 04:44:23

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

编辑:抱歉,我错过了第二部分。但你已经了解了总体思路。否则,枚举并检查 0?

编辑2:好的,摆脱了愚蠢的第二个想法。

Can't you do root.copy(something.get()) before the loop?

EDIT: Sorry, I missed the second bit. But you get the general idea. Otherwise, enumerate and check for 0?

EDIT2: Ok, got rid of the silly second idea.

殊姿 2024-08-23 04:44:23

我不懂 Python,但我使用的模式几乎与您的示例完全相同。
我所做的还使 if 条件成为最常见的条件,因此通常检查 if(first == false )
为什么?对于长循环,first 只会有一次为 true,而其他所有时间都为 false,这意味着在除第一个循环之外的所有循环中,程序将检查条件并跳转到 else 部分。
通过检查第一个是否为假,将只有一次跳转到其他部分。我真的不知道这是否会提高效率,但我还是这么做了,只是为了与我内心的书呆子和平相处。

PS:是的,我知道当进入if部分时,它也必须跳过else才能继续执行,所以可能我的做法没什么用,但感觉很好。 :D

I don't know Python, but I use almost the exact pattern of your example.
What I do also is making the if condition the most frequent, so usually check for if( first == false )
Why? for long loops, first will be true only one time and will be false all the other times, meaning that in all loops but the first, the program will check for the condition and jump to the else part.
By checking for first being false, there will be only one jump to the else part. I don't really know if this adds efficiency at all, but I do it anyway, just to be in peace with my inner nerd.

PS: Yes, I know that when entering the if part, it also has to jump over the else to continue execution, so probably my way of doing it is useless, but it feels nice. :D

行至春深 2024-08-23 04:44:23

你的问题很矛盾。你说“只在第一次迭代中做一些事情”,而实际上你是说在第一次/后续迭代中做一些不同的事情。这就是我尝试的方式:

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

Your question is contradictory. You say "only do something on first iteration", when in fact you are saying do something different on first/subsequent iterations. This is how I would attempt it:

copyfn = root.copy
for member in something.get():
    copyfn(member)
    foo(member)
    copyfn = somewhereElse.copy
逆光飞翔i 2024-08-23 04:44:23

这对我有用

    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  ))

Here is what works for me

    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  ))
源来凯始玺欢你 2024-08-23 04:44:23

使用仅针对第一个成员运行的帮助程序,然后适当地替换自身:(

def copy(member):
    root.copy(member)
    global copy
    copy = somewhereElse.copy

for member in something.get():
    copy(member)
    foo(member)

如果您的循环位于函数内部,请将 global 替换为 nonlocal。)

With a helper that only runs for the first member and then replaces itself appropriately:

def copy(member):
    root.copy(member)
    global copy
    copy = somewhereElse.copy

for member in something.get():
    copy(member)
    foo(member)

(If your loop is inside a function, replace global with nonlocal.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文