【问题标题】:How to pythonically avoid this code duplication with a while loop?如何使用 while 循环以 Python 方式避免这种代码重复?
【发布时间】:2018-11-27 14:32:04
【问题描述】:

我想找到尚不存在的第一个文件名myfile????.txt???? 是一个数字)。这有效:

import os
i = 0
f = 'myfile%04i.txt' % i
while os.path.exists(f):
    i += 1
    f = 'myfile%04i.txt' % i

但我不喜欢f = ...的代码重复。

有没有一种 Pythonic 方法可以避免 while 循环中的代码重复?

注意:我已经发布了一个半满意的解决方案,使用 do/while 成语,正如 Emulate a do-while loop in Python? 的主要答案中提到的那样,但我仍然想知道对于这种特殊情况是否有更好的方法(因此,它不是这个问题的欺骗)。

【问题讨论】:

标签: python loops while-loop code-duplication


【解决方案1】:

您不需要在这里遵循while 范式,带有next() 的嵌套生成器表达式可以工作:

import os
from itertools import count
f = next(f for f in ('myfile%04i.txt' % i for i in count()) if not os.path.exists(f))
print(f)

【讨论】:

  • 完美解决方案(我刚刚编辑,以便我们可以通过复制/粘贴轻松测试它)。
  • @Basj 好的,注意我只是稍微编辑了一下以纠正一个错误(我的)
  • 这真的是pythonic、简洁和明确的!我认为使用生成器 / next() 可以实现,但我没有找到方法,非常感谢!
【解决方案2】:

摆脱f 变量。

import os

i = 0
while os.path.exists('myfile%04i.txt' % i):
    i += 1

【讨论】:

  • 哦,太好了!但是我最后还是需要f,有没有办法得到呢?
  • f 设为变量并将其“提供”给while
  • @Basj 是的,你仍然可以在循环之前初始化f,然后使用while os.path.exists(f % i)
  • 第二种解决方案不起作用,例如,如果您print f,您将获得myfile%04i.txt 而不是myfile0002.txt。所以我们需要在末尾添加f = f % i 才能真正在f 中得到答案。不过,这可能是迄今为止最好的解决方案!
  • 啊,你是对的。不运行它是我的坏事。我将恢复我的编辑,因为这基本上是你开始的。
【解决方案3】:

在写完问题的时候我几乎找到了答案。经过一些修改后,它可以工作了:

import os
i = 0
while True:
    f = 'myfile%04i.txt' % i
    if not os.path.exists(f):
        break
    i += 1
print f

我仍然想知道是否有更 Pythonic 的方式,可能使用迭代器、生成器、next(...) 或类似的东西。

【讨论】:

    【解决方案4】:

    这太简单了吗?

    import os
    f = 'myfile0000.txt'
    while os.path.exists(f):
        i += 1
        f = 'myfile%04i.txt' % i
    

    【讨论】:

    • 它“有效”,就像我的问题代码和我发布的解决方案一样,但我想知道是否有没有重复 f = ... 的解决方案。
    【解决方案5】:

    你可以这样做:

    import os
    from itertools import count
    
    cursor = count()
    it = iter((path for path in map(lambda x: 'myfile%04i.txt' % x, cursor) if not os.path.exists(path)))
    first = next(it, None)
    
    if first:
        print(first)
    

    输出

    myfile0000.txt
    

    【讨论】: