有没有办法回到Python for循环中的一个步骤?

有没有办法回到Python for循环中的一个步骤?,python,loops,for-loop,Python,Loops,For Loop,我希望找到一种方法来有效地模拟从while循环到for循环的相同可能行为,使循环停止或在满足条件时返回一步。原因是我试图实现一个迭代次数很多的计算,根据%%timeit%%,for循环比while循环快4倍 因为循环不会来回移动。他们只需为给定的获取,然后重复调用,直到该方法引发StopIteration 对于序列对象,迭代器只保留一个内部索引,每次调用uuu next uuu以获取序列中的下一个值时,该索引都会递增。该内部索引通常是不可访问的 因此,如果您的特定用例通过“返回”变得更容易,那么

我希望找到一种方法来有效地模拟从while循环到for循环的相同可能行为,使循环停止或在满足条件时返回一步。原因是我试图实现一个迭代次数很多的计算,根据%%timeit%%,for循环比while循环快4倍

因为循环不会来回移动。他们只需为给定的获取,然后重复调用,直到该方法引发StopIteration

对于序列对象,迭代器只保留一个内部索引,每次调用uuu next uuu以获取序列中的下一个值时,该索引都会递增。该内部索引通常是不可访问的

因此,如果您的特定用例通过“返回”变得更容易,那么您必须创建一个迭代器对象来公开索引,或者让您更改下一次调用将产生的值:

向后跳两步

然而,我不希望这比一个while循环更快。虽然循环并不是特别快,但每次迭代测试while条件与调用迭代器没有太大区别。在定时测试中,while条件比较慢,因为它在每次迭代中都会执行Python字节码,并在循环体中递增n,但是范围迭代器完全是用C实现的。上面的迭代器类在Python代码中再次实现了u next uu,因此速度也同样慢

为了演示,我可以向您展示计时差异完全是由于条件和循环体变慢造成的:

>>> import timeit
>>> count, total = timeit.Timer("n = 0\nwhile n < 10 ** 6:\n    n += 1").autorange()
>>> whileloop = total / count
>>> count, total = timeit.Timer("for i in range(10 ** 6):\n    pass").autorange()
>>> forloop = total / count
>>> count, total = timeit.Timer("n < 10 ** 6", "n = 10 ** 5 * 5").autorange()
>>> testbelow = total / count
>>> count, total = timeit.Timer("n += 1", "n = 0").autorange()
>>> increment = total / count
>>> count, total = timeit.Timer("nxt()", "nxt = iter(range(1 << 23)).__next__").autorange()  # enough room to find a good test range
>>> rangeitnext = total / count
>>> whileloop - forloop  # the for loop "speed advantage", per million iterations
0.03363728789991001
>>> (testbelow + increment) - rangeitnext  # relative difference per iteration
-9.191804809961469e-08
>>> ((testbelow + increment) - rangeitnext) * 10 ** 9  # microseconds
-91.9180480996147
上面保留了最后两项,以备您需要处理

或者您可以使用zip和独立迭代器:

from itertools import islice

twoforward = islice(iterable, 2, None)
for twoback, current in zip(iterable, twoforward):
    # twoback and current are paired up at indices i - 2 and i.
至于euler_Differention_mod函数,以下函数实现了相同的工作,而无需提前一段时间计数器。您的函数每次迭代最多计算3次增量,当您在容许范围内有最大更改或尝试了3次时,将移动到下一次迭代:

def euler_differentiate_mod(
    w, bounds=None, delta=1e-3, itern=1000, tols=(10, 0.1), step_mults=(0.1, 10)
):
    if bounds is None:
        bounds = [0] * len(w)

    for _ in range(itern):
        for _ in range(3):
            deltas = [f(delta, *bounds) for f in w]
            maxchange = max(map(abs, deltas[1:]))  # ignore the first delta
            bounds[:] = [b + d for b, d in zip(bounds, deltas)]

            if delta > 1:
                delta *= step_mults[0] / maxchange

            if tols[1] <= maxchange <= tols[0]:
                break

            if delta > 1:
                if tols[0] < maxchange:
                    delta *= step_mults[0] / maxchange
                elif maxchange < tols[1]:
                    delta *= step_mults[1] / maxchange

for循环比while循环快4倍,这是一个有趣的说法。你能分享更多的信息,甚至是一些关于这个观察的代码吗?为什么你说for循环比while快4倍?这不是一个有效的比较,你在比较一个必须执行操作的循环和一个不执行操作的循环。您应该创建一个完整的[X,Y问题。你认为你需要返回循环中的一个步骤,但你没有。而且你的循环原因比while循环快4倍。你也没有发布任何代码。你发布的添加错误的、不相关的代码是一个图像!对。但是,请注意,这只是循环维护的开销。一旦你有了实际的looP体,每个循环的~7Ms的差异几乎肯定会消失在你的有目的的操作的噪音中。好吧,我不明白为什么用户喜欢否决这样的问题,而这又不是一个懒惰的问题,它会产生像你这样的信息丰富的答案。你认为这是一个7点的问题吗?在我看来不是,特别是它是基础性的。我投票支持好的黑客,但我肯定不想调试这样一个宝石production@DeepSpace并不是所有的事情都必须是生产质量。我还提到了我的个人情况,那就是计算物理:这里面没有太多调试,我们只是想让事情快速运转y、 @mariogarc在这方面没有太多调试,我们只是想让事情快速运转,这是一种矛盾修饰法。你想让事情快速运转,但当它们停止时你会怎么做?例如,在这种情况下,For循环何时会变成无限循环?这通常不会发生在Python@DeepSpace:这是我写给illus的我将添加一个更好的替代方案来展示我通常是如何解决这些问题的。
iterator = PositionableSequenceIterator(some_list)
for elem in iterator:
    if somecondition:
        iterator.pos -= 2
    # ...
>>> import timeit
>>> count, total = timeit.Timer("n = 0\nwhile n < 10 ** 6:\n    n += 1").autorange()
>>> whileloop = total / count
>>> count, total = timeit.Timer("for i in range(10 ** 6):\n    pass").autorange()
>>> forloop = total / count
>>> count, total = timeit.Timer("n < 10 ** 6", "n = 10 ** 5 * 5").autorange()
>>> testbelow = total / count
>>> count, total = timeit.Timer("n += 1", "n = 0").autorange()
>>> increment = total / count
>>> count, total = timeit.Timer("nxt()", "nxt = iter(range(1 << 23)).__next__").autorange()  # enough room to find a good test range
>>> rangeitnext = total / count
>>> whileloop - forloop  # the for loop "speed advantage", per million iterations
0.03363728789991001
>>> (testbelow + increment) - rangeitnext  # relative difference per iteration
-9.191804809961469e-08
>>> ((testbelow + increment) - rangeitnext) * 10 ** 9  # microseconds
-91.9180480996147
from collections import deque

preceding = deque(maxlen=2)
for item in iterable:
    if condition:
        # process items in preceding

    preceding.append(item)
from itertools import islice

twoforward = islice(iterable, 2, None)
for twoback, current in zip(iterable, twoforward):
    # twoback and current are paired up at indices i - 2 and i.
def euler_differentiate_mod(
    w, bounds=None, delta=1e-3, itern=1000, tols=(10, 0.1), step_mults=(0.1, 10)
):
    if bounds is None:
        bounds = [0] * len(w)

    for _ in range(itern):
        for _ in range(3):
            deltas = [f(delta, *bounds) for f in w]
            maxchange = max(map(abs, deltas[1:]))  # ignore the first delta
            bounds[:] = [b + d for b, d in zip(bounds, deltas)]

            if delta > 1:
                delta *= step_mults[0] / maxchange

            if tols[1] <= maxchange <= tols[0]:
                break

            if delta > 1:
                if tols[0] < maxchange:
                    delta *= step_mults[0] / maxchange
                elif maxchange < tols[1]:
                    delta *= step_mults[1] / maxchange