21

So, Python functions can return multiple values. It struck me that it would be convenient (though a bit less readable) if the following were possible.

a = [[1,2],[3,4]]

def cord():
    return 1, 1

def printa(y,x):
    print a[y][x]

printa(cord())

...but it's not. I'm aware that you can do the same thing by dumping both return values into temporary variables, but it doesn't seem as elegant. I could also rewrite the last line as "printa(cord()[0], cord()[1])", but that would execute cord() twice.

Is there an elegant, efficient way to do this? Or should I just see that quote about premature optimization and forget about this?

alain.janinm
  • 19,951
  • 10
  • 65
  • 112
James
  • 2,626
  • 5
  • 37
  • 51

3 Answers3

32
printa(*cord())

The * here is an argument expansion operator... well I forget what it's technically called, but in this context it takes a list or tuple and expands it out so the function sees each list/tuple element as a separate argument.

It's basically the reverse of the * you might use to capture all non-keyword arguments in a function definition:

def fn(*args):
    # args is now a tuple of the non-keyworded arguments
    print args

fn(1, 2, 3, 4, 5)

prints (1, 2, 3, 4, 5)

fn(*[1, 2, 3, 4, 5])

does the same.

David Z
  • 128,184
  • 27
  • 255
  • 279
  • And the documentation: http://docs.python.org/tutorial/controlflow.html#tut-unpacking-arguments – regan Mar 27 '09 at 20:03
6

Try this:

>>> def cord():
...     return (1, 1)
...
>>> def printa(y, x):
...     print a[y][x]
...
>>> a=[[1,2],[3,4]]
>>> printa(*cord())
4

The star basically says "use the elements of this collection as positional arguments." You can do the same with a dict for keyword arguments using two stars:

>>> a = {'a' : 2, 'b' : 3}
>>> def foo(a, b):
...    print a, b
...
>>> foo(**a)
2 3
Jason Baker
  • 192,085
  • 135
  • 376
  • 510
3

Actually, Python doesn't really return multiple values, it returns one value which can be multiple values packed into a tuple. Which means that you need to "unpack" the returned value in order to have multiples. A statement like

x,y = cord()

does that, but directly using the return value as you did in

printa(cord())

doesn't, that's why you need to use the asterisk. Perhaps a nice term for it might be "implicit tuple unpacking" or "tuple unpacking without assignment".

Albert Visser
  • 1,124
  • 6
  • 5