More Pythonic Way to Run a Process X Times [closed]
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 months ago.
Improve this questionWhich is more pythonic?
While loop:
count = 0
while count < 50:
print "Some thing"
count = count + 1
For loop:
for i in range(50):
print "Some thing"
Edit: not duplicate because this has answers to determine whic开发者_Go百科h is clearer, vs. how to run a range without 'i' -- even though that ended up being the most elegant
Personally:
for _ in range(50):
print "Some thing"
if you don't need i
. If you use Python < 3 and you want to repeat the loop a lot of times, use xrange
as there is no need to generate the whole list beforehand.
If you are after the side effects that happen within the loop, I'd personally go for the range()
approach.
If you care about the result of whatever functions you call within the loop, I'd go for a list comprehension or map
approach. Something like this:
def f(n):
return n * n
results = [f(i) for i in range(50)]
# or using map:
results = map(f, range(50))
The for loop is definitely more pythonic, as it uses Python's higher level built in functionality to convey what you're doing both more clearly and concisely. The overhead of range vs xrange, and assigning an unused i
variable, stem from the absence of a statement like Verilog's repeat
statement. The main reason to stick to the for range solution is that other ways are more complex. For instance:
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"
Using repeat instead of range here is less clear because it's not as well known a function, and more complex because you need to import it. The main style guides if you need a reference are PEP 20 - The Zen of Python and PEP 8 - Style Guide for Python Code.
We also note that the for range version is an explicit example used in both the language reference and tutorial, although in that case the value is used. It does mean the form is bound to be more familiar than the while expansion of a C-style for loop.
How about?
while BoolIter(N, default=True, falseIndex=N-1):
print 'some thing'
or in a more ugly way:
for _ in BoolIter(N):
print 'doing somthing'
or if you want to catch the last time through:
for lastIteration in BoolIter(N, default=False, trueIndex=N-1):
if not lastIteration:
print 'still going'
else:
print 'last time'
where:
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__()
There is not a really pythonic way of repeating something. However, it is a better way:
map(lambda index:do_something(), xrange(10))
If you need to pass the index then:
map(lambda index:do_something(index), xrange(10))
Consider that it returns the results as a collection. So, if you need to collect the results it can help.
精彩评论