简体   繁体   English

什么是在循环中在两个函数之间交替的pythonic方法

[英]What is the pythonic way to alternate between two functions in a loop

It seems like a simple question to me, but a search yielded nothing useful. 对我来说这似乎是一个简单的问题,但搜索没有产生任何用处。

I have code like below: 我有如下代码:

    for key, v in enumerate(ranges):

        ### Used to switch between voltage steps
        second_iter = 0

        for step in v:

            ### Set voltage sources to differential voltages
            if second_iter == 0:
                self.tf.institf.dcm.vsource1(step)
                second_iter = 1
            elif second_iter == 1:
                self.tf.institf.dcm.vsource2(step)

            self.measure_something()

v is a 2 element list. v是2元素列表。 ranges is a list of v's. 范围是v的列表。 I want to cycle through each v, but use the second element in a different function each time. 我想遍历每个v,但每次使用不同函数中的第二个元素。

Is there a pythonic way to write the code above? 是否有一种pythonic方式来编写上面的代码?

Edit: To clarify, I want to do some separate code afterwards which measures something. 编辑:为了澄清,我想在之后做一些单独的代码测量某些东西。 So I can't set both functions at the same time. 所以我不能同时设置这两个功能。

Your code is very little intuitive... Is this not enough to do that, without abusing loops? 你的代码非常直观......这不足以做到这一点,而不会滥用循环吗?

vsource1 = self.tf.institf.dcm.vsource1
vsource2 = self.tf.institf.dcm.vsource2

for key, (v1, v2) in enumerate(ranges):

    vsource1(v1)
    # Do some other stuff

    vsource2(v2)
    # Do some other stuff  

Alternatively, if the "stuff" is the same you can indeed use a loop like this to avoid repeating yourself: 或者,如果“stuff”是相同的,你确实可以使用这样的循环来避免重复自己:

vsource1 = self.tf.institf.dcm.vsource1
vsource2 = self.tf.institf.dcm.vsource2

funcs = (vsource1, vsource2)

for key, steps in enumerate(ranges):
    for func, step in zip(funcs, steps):
        func(step)
        # Do some other stuff

I would do it like this: 我会这样做:

for key, v in enumerate(range(0, 100)):
     [fun_call1() if key % 2 else fun_call2()]

This reduces the amount of code and reduces the need of conditional evaluation to 1 for each iteration. 这减少了代码量,并将每次迭代的条件评估需求减少到1。

for key, v in enumerate(ranges):

    if key % 2 == 0:
        self.tf.institf.dcm.vsource1(v[0])
    else:
        self.tf.institf.dcm.vsource2(v[1])

If v is a 2 element list, I'd write it like this: 如果v是2元素列表,我会这样写:

for key, (step1, step2) in enumerate(ranges):
    self.tf.institf.dcm.vsource1(step1)
    self.measure_something()

    self.tf.institf.dcm.vsource2(step2)
    self.measure_something()

Pythonic doesn't always mean to use the most advanced functions to generate the shortest code. Pythonic并不总是意味着使用最先进的函数来生成最短的代码。 Because of the fixed length of v in your example, I'd say that the solution above is the easiest to read and therefore pythonic. 由于你的例子中v的固定长度,我会说上面的解决方案是最容易阅读的,因此pythonic。

Simple indexing into second list can help avoid loop and second_iter variable 简单索引到第二个列表可以帮助避免循环和second_iter变量

for key, v in enumerate(ranges):
    self.tf.institf.dcm.vsource1(v[0])
    self.measure_something()

    self.tf.institf.dcm.vsource2(v[1])
    self.measure_something()

You could use itertools.cycle and zip : 你可以使用itertools.cyclezip

from itertools import cycle

vsources = [self.tf.institf.dcm.vsource1, self.tf.institf.dcm.vsource2]


for key, v in enumerate(ranges):
    for (step, vsource) in zip(v, cycle(vsources)):
        ### Set voltage sources to differential voltages
        vsource(step)

Edit: I realise now that there is only two values in each v , so no need to use cycle . 编辑:我现在意识到每个v只有两个值,所以不需要使用cycle Delgan's answer seems to cover this well, so I'll just leave this as-is, and defer to his answer. 德尔甘的答案似乎很好地涵盖了这一点,所以我只是按原样离开,并按照他的回答。

Not strictly pythonic, but you can use the remainder operator to switch between the two functions: 不是严格pythonic,但您可以使用余数运算符在两个函数之间切换:

funcs = [func1, func2]

for i, voltage in enumerate(ranges):
    for step in voltage:
        func = funcs[i % 2]
        func(step)

OR 要么

This one's not DRY, but probably makes better use of the cache by grouping all calls to each function. 这个不是DRY,但可能通过将对每个函数的所有调用分组来更好地利用缓存。 Slice ranges into the two arrays you need, then call the function on the subarray: 切片ranges到你需要的两个数组,然后在子数组上调用函数:

range1 = ranges[0::2]
range2 = ranges[1::2]

for step in range1: func1(step)
for step in range2: func2(step)

Inlining the slices: 内联切片:

for step in ranges[0::2]: func1(step)
for step in ranges[1::2]: func2(step)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM