Idiomatic Python: 'times' loop
Question:
Say I have a function foo
that I want to call n
times. In Ruby, I would write:
n.times { foo }
In Python, I could write:
for _ in xrange(n): foo()
But that seems like a hacky way of doing things.
My question: Is there an idiomatic way of doing this in Python?
Answers:
You’ve already shown the idiomatic way:
for _ in range(n): # or xrange if you are on 2.X
foo()
Not sure what is “hackish” about this. If you have a more specific use case in mind, please provide more details, and there might be something better suited to what you are doing.
Fastest, cleanest is itertools.repeat:
import itertools
for _ in itertools.repeat(None, n):
foo()
The question pre-supposes that calling foo() n times is an a priori necessary thing. Where did n come from? Is it the length of something iterable? Then iterate over the iterable. As I am picking up Python, I find that I’m using few to no arbitrary values; there is some more salient meaning behind your n that got lost when it became an integer.
Earlier today I happened upon Nicklaus Wirth’s provocative paper for IEEE Computer entitled Good Ideas – Through the Looking Glass (archived version for future readers). In section 4 he brings a different slant on programming constructs that everyone (including himself) has taken for granted but that hold expressive flaws:
“The generality of Algol’s for
statement should have been a warning
signal to all future designers to
always keep the primary purpose of a
construct in mind, and to be weary of
exaggerated generality and complexity,
which may easily become
counter-productive.”
The algol for
is equivalent to the C/Java for
, it just does too much. That paper is a useful read if only because it makes one not take for granted so much that we so readily do. So perhaps a better question is “Why would you need a loop that executes an arbitrary number of times?”
If you want the times
method, and you need to use it on your own functions, try this:
def times(self, n, *args, **kwargs):
for _ in range(n):
self.__call__(*args, **kwargs)
import new
def repeatable(func):
func.times = new.instancemethod(times, func, func.__class__)
return func
now add a @repeatable
decorator to any method you need a times
method on:
@repeatable
def foo(bar):
print bar
foo.times(4, "baz") #outputs 4 lines of "baz"
Say I have a function foo
that I want to call n
times. In Ruby, I would write:
n.times { foo }
In Python, I could write:
for _ in xrange(n): foo()
But that seems like a hacky way of doing things.
My question: Is there an idiomatic way of doing this in Python?
You’ve already shown the idiomatic way:
for _ in range(n): # or xrange if you are on 2.X
foo()
Not sure what is “hackish” about this. If you have a more specific use case in mind, please provide more details, and there might be something better suited to what you are doing.
Fastest, cleanest is itertools.repeat:
import itertools
for _ in itertools.repeat(None, n):
foo()
The question pre-supposes that calling foo() n times is an a priori necessary thing. Where did n come from? Is it the length of something iterable? Then iterate over the iterable. As I am picking up Python, I find that I’m using few to no arbitrary values; there is some more salient meaning behind your n that got lost when it became an integer.
Earlier today I happened upon Nicklaus Wirth’s provocative paper for IEEE Computer entitled Good Ideas – Through the Looking Glass (archived version for future readers). In section 4 he brings a different slant on programming constructs that everyone (including himself) has taken for granted but that hold expressive flaws:
“The generality of Algol’s
for
statement should have been a warning
signal to all future designers to
always keep the primary purpose of a
construct in mind, and to be weary of
exaggerated generality and complexity,
which may easily become
counter-productive.”
The algol for
is equivalent to the C/Java for
, it just does too much. That paper is a useful read if only because it makes one not take for granted so much that we so readily do. So perhaps a better question is “Why would you need a loop that executes an arbitrary number of times?”
If you want the times
method, and you need to use it on your own functions, try this:
def times(self, n, *args, **kwargs):
for _ in range(n):
self.__call__(*args, **kwargs)
import new
def repeatable(func):
func.times = new.instancemethod(times, func, func.__class__)
return func
now add a @repeatable
decorator to any method you need a times
method on:
@repeatable
def foo(bar):
print bar
foo.times(4, "baz") #outputs 4 lines of "baz"