66

I've been looking at passing arrays, or lists, as Python tends to call them, into a function.

I read something about using *args, such as:

def someFunc(*args)
    for x in args
        print x

But not sure if this is right/wrong. Nothing seems to work as I want. I'm used to be able to pass arrays into PHP function with ease and this is confusing me. It also seems I can't do this:

def someFunc(*args, someString)

As it throws up an error.

I think I've just got myself completely confused and looking for someone to clear it up for me.

codeforester
  • 39,467
  • 16
  • 112
  • 140
Jack Franklin
  • 3,765
  • 6
  • 26
  • 34
  • 2
    http://docs.python.org/tutorial/controlflow.html#arbitrary-argument-lists briefly details to use the asterisk. It means you can pass an arbitrary amount of arguments, and they'll be wrapped up in a tuple (which can be accessed like a list within the function). An argument name with an asterisk has to come last so Python knows which is which. – JAL Oct 18 '10 at 16:18
  • 1
    "as Python tends to call them"? It's not a "tendency". It's a matter of definition. – S.Lott Oct 18 '10 at 17:48
  • 17
    S.Lott,calm down! I think you're being a bit harsh there - has that comment added anything to the conversation? no. – Jack Franklin Oct 18 '10 at 18:49
  • 7
    You are allowed to think it's harsh. However, word choice matters quite a bit, since other people, less knowledgeable will read this. I'm suggesting that "tends to call them" is a poor choice of words because it will confuse someone. There are enough Python questions with "array" instead of "list". This indicates folks aren't using the right terms and aren't succeeding in search existing documentation. There is enough confusion. It's a 'list'. Really. You can use that word, too, without fear of contradiction. – S.Lott Oct 18 '10 at 20:01
  • 6
    The funniest part... while I appreciate S.Lott's care with words, Python lists are actually implemented as dynamic arrays... lol. – anon01 Dec 17 '17 at 08:12
  • This is unclear: is the intent to pass *multiple arguments, created separately* from the elements of the list? Or is it to pass *one argument, which is* the list? – Karl Knechtel Mar 29 '23 at 00:35

6 Answers6

95

When you define your function using this syntax:

def someFunc(*args):
    for x in args
        print x

You're telling it that you expect a variable number of arguments. If you want to pass in a List (Array from other languages) you'd do something like this:

def someFunc(myList = [], *args):
    for x in myList:
        print x

Then you can call it with this:

items = [1,2,3,4,5]

someFunc(items)

You need to define named arguments before variable arguments, and variable arguments before keyword arguments. You can also have this:

def someFunc(arg1, arg2, arg3, *args, **kwargs):
    for x in args
        print x

Which requires at least three arguments, and supports variable numbers of other arguments and keyword arguments.

g.d.d.c
  • 46,865
  • 9
  • 101
  • 111
  • 19
    Beware of using mutable objects as default arguments! def someFunc(myList = []): myList.append(1) someFunc called twice without argument will return [1, 1], because default arguments, are constructed only once, when the function definition is evaluated. – Rafał Rawicki Oct 18 '10 at 16:16
  • What does `*args` do in your second example, `def someFunc(myList = [], *args):`, that the simpler `def someFunc(myList = []):` doesn't do? Thanks. EDIT: Oh wait, it means that you can pass `myList` as either a list or as a tuple. Either way works. Correct? – PatrickT May 11 '20 at 03:40
  • @PatrickT - nope. It means the function takes the `myList` parameter (and provides a default) and that it also takes an open ended number of additional arguments (they are not used in the example). – g.d.d.c May 11 '20 at 16:10
  • 1
    @g.d.d.c, thanks for your reply. So if I pass a tuple like `someFunc(1, 2)` the `1` goes into `myList` while `2` is one of the optional additional arguments. Did I get it this time? – PatrickT May 11 '20 at 16:15
  • 1
    @PatrickT - yes, but you're mixing up some things terminology wise, which may contribute to confusion later. When you write `someFunc(1, 2)` you are not 'passing a tuple' you are 'invoking the function with two arguments'. To actually pass a tuple, you would write `someFunc((1, 2))`. Note this would place the tuple value `(1, 2)` in `myList` and the extra args would still be empty. You could write `someFunc((1, 2), 3)` in which case you both 'pass a tuple' and 'provide additional arguments'. – g.d.d.c May 11 '20 at 18:50
  • @g.d.d.c Thank you so much. I did not realize the brackets around the tuple would be needed when passing to a function (I typically see tuples used as in `x,y = 1,2` without brackets). It's all much clearer now. – PatrickT May 11 '20 at 18:59
  • Thanks to this question , answer and comment by @RafałRawicki I have learnt a good lesson- here is the explenation for why mutable defaults are dangerous: https://florimond.dev/en/posts/2018/08/python-mutable-defaults-are-the-source-of-all-evil/#:~:text=Do%20not%20use%20mutable%20default,mutable%20value%20inside%20the%20function. – KenBuckley Feb 27 '23 at 14:23
37

You can pass lists just like other types:

l = [1,2,3]

def stuff(a):
   for x in a:
      print a


stuff(l)

This prints the list l. Keep in mind lists are passed as references not as a deep copy.

JoshD
  • 12,490
  • 3
  • 42
  • 53
8

You don't need to use the asterisk to accept a list.

Simply give the argument a name in the definition, and pass in a list like

def takes_list(a_list):
    for item in a_list:
         print item
JAL
  • 21,295
  • 1
  • 48
  • 66
8

Python lists (which are not just arrays because their size can be changed on the fly) are normal Python objects and can be passed in to functions as any variable. The * syntax is used for unpacking lists, which is probably not something you want to do now.

Gintautas Miliauskas
  • 7,744
  • 4
  • 32
  • 34
2
def sumlist(items=[]):
    sum = 0
    for i in items:
        sum += i

    return sum

t=sumlist([2,4,8,1])
print(t)
M--
  • 25,431
  • 8
  • 61
  • 93
ishaj
  • 91
  • 1
  • 4
1

There is a way how to pass list directly instead of function params. In this scenario you have function with fixed number of parameters, would like to pack these into the list and call the function using your list.

The function scipy.optimize.curve_fit utilizes this as it expect the function parametrized by apriori unknown number of values, e.g. you can specify

import numpy as np
def f(x, a0, a1, a2):
   return a0+a1*np.exp(a2*x)

To have a function parametrized by three parameters. Then you call

fit, cov = curve_fit(f, xdata, ydata)

and the function returns fit list of the length corresponding to the number of parameters, interestingly you can then obtain value v of function parametrized by fit params at the point x by calling

fit=[1,2,3]
x=0
v = f(x, *fit)

See scipy sources

VojtaK
  • 483
  • 4
  • 13