1

Consider this minimal example:

def arfunc(x,*a):
    sa=a[1]
    return sa

b=arfunc(1.,(5.,2.))
print(b)

I need to pass an array whose length may vary to a function and then work with individual array elements within that function. If I exchange a[1] by a[0] in the function, the entire list is returned. Why does this not work, and how do I make it work?

codeforester
  • 39,467
  • 16
  • 112
  • 140
TomR
  • 133
  • 1
  • 14
  • Could you please more elaborate? what is x? Running the current code returns an error... – Enayat Mar 04 '19 at 13:34
  • 1
    `(5.,2.)` is not an array, it is a *tuple*. – cdarke Mar 04 '19 at 13:34
  • Not sure if I understood your question correctly, but see here: [What does ** (double star/asterisk) and * (star/asterisk) do for parameters?](https://stackoverflow.com/questions/36901/what-does-double-star-asterisk-and-star-asterisk-do-for-parameters). It says: "The *args will give you all function parameters as a tuple." You can add a print statement before the `sa=a[1]` line, and you will see that `a == ((5., 2.),)` - a tuple of one element which is also a tuple. – Georgy Mar 04 '19 at 13:35
  • 2
    Possible duplicate of [What does \*\* (double star/asterisk) and \* (star/asterisk) do for parameters?](https://stackoverflow.com/questions/36901/what-does-double-star-asterisk-and-star-asterisk-do-for-parameters) – Georgy Mar 04 '19 at 13:36

5 Answers5

3

A function taking variable arguments (*args) expects them as several arguments:

b=arfunc(1., 5., 2.)
print(b)

If you want to use the function as you did, remove the asterisk:

def arfunc(x, a):
    ...
L3viathan
  • 26,748
  • 2
  • 58
  • 81
  • This example is actually a test for a call of scipy.optimize.curve_fit (https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.curve_fit.html), where the initial guesses p0 are passed as a tuple and the function must have the form f(xdata, *params). If I pass the tuple p0, I can't access its elements in the function the way shown in the example; if I omit the * in the def, I cannot pass more than one additional argument in params. The question https://stackoverflow.com/questions/54974948/python-curve-fit-cannot-pass-array-with-init-guess shows my problem in context. – TomR Mar 04 '19 at 14:07
  • So you have to use this signature and call, but only care about the first element? Just do `a = a[0]` inside the function body. – L3viathan Mar 04 '19 at 14:24
  • No, I care about all of them. If you look at the definition of the function pipoly at the beginning of that other thread (https://stackoverflow.com/questions/54974948/python-curve-fit-cannot-pass-array-with-init-guess), you see that I try to loop through the elements of the tuple. – TomR Mar 04 '19 at 14:31
1

* symbol in function definition allows a function to have a variadic type. The variable a will become a collection of all of the positional arguments passed after the first one: x.

There is no need to use the * symbol to let a have a variable length. Lists already have that property in Python.

skullgoblet1089
  • 554
  • 4
  • 12
1

you missed one thing that is if we have to pass the variable length argument(called Arbitrary Arguments in python) with a function you need to add *(asterisk)

def arfunc(x,*a):   # here *a can hold argument that may vary in numbers.
    sa=a[1]
    return sa

b=arfunc(1.,*(5.,2.)) # here you also have to provide a arbitary arguments like this.
print(b)

For better understanding refer below written code:

def arfunc(x,*a):
    sa=a[1]
    return sa

d = 1.
e = (5.,2.)

b=arfunc(d,*e)
print(b)
Abhishek-Saini
  • 733
  • 7
  • 11
0

You can pass list or list of list.

Eg

List -

 [1,2,3,4]

List of lists -

[1,2,3[4,5,6]]

If thats what you are trying to do.

Shahir Ansari
  • 1,682
  • 15
  • 21
0

The star '*' operator is used to unpack arguments from a list. It is similar to the varargs in C/C++ or Java when a function expects a random number of arguments. You cannot change the original list / array in this case.

However, if you need to pass an array on that you will change inside the function, and then returned it back, I recommend you to pass and array or list to the function without the unpacking operator *. Example:

def try_to_change_list_contents(the_list):
   print('got', the_list)
   the_list.append('four')
   print('changed to', the_list)

outer_list = ['one', 'two', 'three']

print('before, outer_list =', outer_list)
try_to_change_list_contents(outer_list)
print('after, outer_list =', outer_list)

You can take a look at this post too: topic

Hichem BOUSSETTA
  • 1,791
  • 1
  • 21
  • 27