12

I want this:

[foo() for _ in xrange (100)]

but beautifuller. ?

1
  • 4
    Coming from a C# background, that's pretty beautiful. It's beautifuller than Enumerable.Range(0, 100).Select(x => foo());. Commented Jul 13, 2011 at 19:35

6 Answers 6

8

You can write a generator repeat like this:

def repeat(times, func, *args, **kwargs):
    for _ in xrange(times):
        yield func(*args, **kwargs)

Then:

list(repeat(100, foo))

It also accepts arguments to be passed on to the function, so you can:

from random import randint
list(repeat(100, randint, 1, 100))   # 100 random ints between 1 and 100

Since it's a generator, you can pipe it into any kind of iterable, be it a list (as here) or a tuple or a set, or use it in a comprehension or a loop.

Sign up to request clarification or add additional context in comments.

Comments

5

I'm afraid you're not gonna get it any prettier than that in Python, except that some people would advise against _ for an "anonymous" variable. This is the Pythonic idiom for doing what you want.

(The _ can be considered confusing to novices because it can be mistaken for special syntax. I use it, but only in the "expert parts" of my code. I also encounter it more and more often, but opinion still seems a bit divided on this one.)

4 Comments

I thought _ was the pythonic name for an unused variable?
@Davy8: it seems not everyone agrees; @Sven Marnach got two upvotes went he told me not to use _ this way.
One advantage of using _ is that it will prevent PyLint from complaining about an unused variable. I think any variable name starting with _ will work.
I personally prefer something like ignored or _ignored, since that actually says ignored in the name of the ignored variable.
3

Depending on your definition of "beautifuller", you may prefer this:

map(lambda x: foo(), xrange(100))

Although what you have already is much nicer IMO.

1 Comment

if you have to use lambda, map() is (well, by most everyone I've heard an opinion from) considered less pythonic than the equivalent list comprehension.
2

Depending on what it does, you can make foo() a generator.

1 Comment

in my case (foo being a simple function that returns different unparameterized results on each call), making it a generator seems to be overkill.
2

Your list comprehension is already beatiful and effective but if you need several options to do the same things then i think you can use map here. In case you need to call a certain function the specified number of times use:

# in case your func looks like
def func():
    # do something
#then
map(func(), xrange(numberOfTimes))

In case your function need value from range then you can use map with lambda:

# in case your func looks like
def func(value):
    # do something with value
#then
map(lambda val: func(val), xrange(numberOfTimes))

Or in case you need to use data from several lists of the same length:

# in case your func looks like
def func(value1, value2):
    # do something with values
#then
map(lambda val: func(*val), zip(xrange(10), xrange(10,20)))

And so on...

Comments

1

In case foo() always returns the same result, you could use

[foo()]*100

This has the advantage that foo() is only called once.

Edit: As @larsmans points out this only makes sense though if foo() returns an immutable result.

In all other cases, your solution is fine!

3 Comments

But if foo returns mutable results, even if they compare equal by ==, this blows up in your face.
this is just wrong as foo() is called only once, as opposed to 100 calls in OP: [randint(1,100)]*5 gives [26, 26, 26, 26, 26]
That's why I pointed out that foo() has to always return the same result -- randint() clearly does not do that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.