X次运行流程的更多Pythonic方式


90

哪个更pythonic?

While循环:

count = 0
while count < 50:
    print "Some thing"
    count = count + 1

对于循环:

for i in range(50):
    print "Some thing"

编辑:不重复,因为这有答案可以确定哪个更清晰,而不是如何在不使用“ i”的情况下运行范围-即使最终结果是最优雅的


8
投票以补偿反对票:如果Lionel提出这个问题,其他人可能会有相同的问题,下面的答案将很有用。
Eric O Lebigot

2
“ Pythonic”一词已被过度使用。它是“可读”和“易于理解”的同义词。至少在Python中。
darioo

Answers:


110

亲身:

for _ in range(50):
    print "Some thing"

如果你不需要i。如果您使用Python <3,并且想重复多次循环,请使用,xrange因为不需要事先生成整个列表。


15
但是请注意_映射到gettext转换函数。
Gintautas Miliauskas,2010年

感谢您的回答;这是我不使用for循环的主要原因,因为我在“ i”中有一个未使用的变量。
Lionel

6
_就像其他任何变量一样。它仅在REPL中具有特殊意义。OP也可能坚持使用i
vezult

2
@vezult我喜欢它,因为它清楚表明该语句中未使用该变量。可能有一个原因使它难以为继i吗?
ryanjdillon

6
我坚信添加小马,尤其是在听起来合适的时候……对于range(50)中的小马:print(“ neigh”)#python 3
Paul

3

for循环绝对是Python风格的,因为它使用Python的更高级别的内置功能来更清楚,简洁地传达您正在做的事情。范围与xrange的开销以及分配未使用的i变量的原因是缺少诸如Verilog的repeat语句之类的语句。坚持使用范围解决方案的主要原因是其他方式更为复杂。例如:

from itertools import repeat

for unused in repeat(None, 10):
    del unused   # redundant and inefficient, the name is clear enough
    print "This is run 10 times"

在这里使用repeat而不是range不太清楚,因为它不是一个众所周知的函数,而更加复杂,因为您需要导入它。如果需要参考,则主要的样式指南为PEP 20-The Zen of PythonPEP 8-Python代码样式指南

我们还注意到,for range版本是在语言参考教程中,尽管在这种情况下使用的是值。这确实意味着该形式肯定比C样式for循环的while扩展更熟悉。


直接使用重复的东西会更好,即:for s in repeat('This is run 10 times', 10): print s??
F1Rumors

当然!但是示例代码中的打印内容只是重复代码部分的一个示例,对此可能没有中心对象。
Yann Vernier

Python核心开发人员说,这比使用range() twitter.com/raymondh/status/1144527183341375488
Chris_Rands

确实更快,因为它不需要int为每次迭代查找或创建不同的对象。但是,程序员的时间可能比执行时间更有价值。
Yann Vernier19年

2

如果您是在循环中发生副作用,我个人会考虑 range()方法。

如果您关心循环中调用的任何函数的结果,那么我将寻求列表理解或map方法。像这样:

def f(n):
    return n * n

results = [f(i) for i in range(50)]
# or using map:
results = map(f, range(50))

结果=(f代表我在范围(50)中的f)
Luka Rahne

1
结果= itertools.imap(f,range(50))
Luka Rahne

@ralu,仅当您不需要重复或随机访问结果时。
aaronasterling

2
result = tuple(results)并且比列表快得多,因为在tuple上切片是O(1)
Luka Rahne

-3

怎么样?

while BoolIter(N, default=True, falseIndex=N-1):
    print 'some thing'

或更丑陋的方式:

for _ in BoolIter(N):
    print 'doing somthing'

或者,如果您想通过以下方式来赶上最后一次:

for lastIteration in BoolIter(N, default=False, trueIndex=N-1):
    if not lastIteration:
        print 'still going'
    else:
        print 'last time'

哪里:

class BoolIter(object):

    def __init__(self, n, default=False, falseIndex=None, trueIndex=None, falseIndexes=[], trueIndexes=[], emitObject=False):
        self.n = n
        self.i = None
        self._default = default
        self._falseIndexes=set(falseIndexes)
        self._trueIndexes=set(trueIndexes)
        if falseIndex is not None:
            self._falseIndexes.add(falseIndex)
        if trueIndex is not None:
            self._trueIndexes.add(trueIndex)
        self._emitObject = emitObject


    def __iter__(self):
        return self

    def next(self):
        if self.i is None:
            self.i = 0
        else:
            self.i += 1
        if self.i == self.n:
            raise StopIteration
        if self._emitObject:
            return self
        else:
            return self.__nonzero__()

    def __nonzero__(self):
        i = self.i
        if i in self._trueIndexes:
            return True
        if i in self._falseIndexes:
            return False
        return self._default

    def __bool__(self):
        return self.__nonzero__()

-5

没有一种真正的pythonic方式重复某件事。但是,这是一种更好的方法:

map(lambda index:do_something(), xrange(10))

如果您需要传递索引,则:

map(lambda index:do_something(index), xrange(10))

考虑它返回结果作为一个集合。因此,如果您需要收集结果,它将有所帮助。


这不仅不是真的更好(函数调用开销,鲜为人知的lambda表达式,将未使用的结果收集在列表中),而且10并不是可迭代的。
Yann Vernier 2014年

是的,xrange(10)不能是10。我说的更好,因为您不需要编写函数或进行循环。但是,正如我所说,这不是真正的pythonic方法。我更改了代码,谢谢。
2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.