args and tuple expansion¶

In [6]:
import numpy as np

• Functions like fsolve, quad and others have an argument called args that you can set to have those functions pass extra arguments to the function provide.
• But fsolve and quad (etc.) don't know how many arguments there are, and there could be an arbitrary number.
• Tuple expansion to the rescue!

Example 1¶

• Below, function f can take any number of arguments.
• args is a tuple, and the * part of *args can be thought of as collapsing the provided list of arguments into the tuple args.
• The name args doesn't matter. It can be anything.
• You can then loop over the elements of args.
In [7]:
def f(*args):
print(args)        # args is a tuple
for a in args:     # loop over elements of args
print(a)

f(1.1, 2.2, 3.3)       # call the func with multiple arguments

(1.1, 2.2, 3.3)
1.1
2.2
3.3


Example 2¶

• Below, function f takes three arguments.
• When calling the function, we first make a tuple with three elements,
• Then we expand the tuple into values using *xyz.
• The * part of *xyz acts to expand the tuple into elements that are then placed in the individual arguments that the function takes.
In [12]:
def f(x,y,z):
print(x)
print(y)
print(z)

xyz = (1.1, 2.2, 3.3)
f(*xyz)

1.1
2.2
3.3


Example 3¶

• Write your own version of quad that uses the trapazoid method, and passes in extra arguments that my function will need.
• See the line fx = f(x, *args) where the tuple of args I pass in to myQuad is expanded into the coefficients c0, c1, and c2 of my quadratic function, defined below.

Trapazoid method: $$I = \Delta x\sum_{i=0}^n f_i - \frac{\Delta x}{2}(f_0-f_n)$$

Do the following integral: \begin{align} &I = \int_0^2f(x,c0,c1,c2)dx,\\ &\phantom{xxxxxxx}f(x,c_0,c_1,c_2) = c_2x^2 + c_1x + c_0. \end{align}

In [ ]:
def myQuad(f, a, b, n=100, args=None):
x = np.linspace(a,b,n)
Δx = x[1]-x[0]
if args is None:
fx = f(x)
else:
fx = f(x, *args)

I = Δx*np.sum(fx) - Δx/2*(fx[0] + fx[-1])

return I

#---------------

def f(x, c0, c1, c2):
return c2*x**2 + c1*x + c0

#---------------

I = myQuad(f, 0, 2, args=(1.1, 2.2, 3.3))
print(I)


kwargs¶

• Can use keyword arguments directly.
• Order doesn't matter
• Pass a dictionary using names and values
• Expand with a double star: **
In [1]:
def f(x,y,z):
print(x)
print(y)
print(z)

#------------ args:

args = (1.1, 2.2, 3.3)
f(*args)

print()

#------------ kwargs:
kwargs = {'z':3.3, 'x':1.1, 'y':2.2}   # notice the order
f(**kwargs)

1.1
2.2
3.3

1.1
2.2
3.3

In [9]:
def f(**kwargs):
for k,v in kwargs.items():
print(k,v)

f(param1=1.1, param2=2.2, param3=3.3)

param1 1.1
param2 2.2
param3 3.3


call order¶

• If using formal (usual) arguments (fargs), args, and kwargs, use this order:
f(fargs, *args, **kwargs)
In [ ]: