1

I am trying to figure out if I can leave an optional argument out (use it's default value) when using *args in Python. The following code works through "print(a)", so explicitly including the optional argument h in the deriv function call works. Can I leave it (h) out somehow? My attempts ("b = ...", "c = ...", "d = ...") fail. Is there another way?

def deriv(f, x, h=1.e-9, *params):
    return (f(x+h, *params)-f(x-h, *params))/(2.*h)

def f1(x, a, p):
    return a*x**p

a = deriv(f1, 3, 1.e-9, 4, 5)
print(a)

b = deriv(f1, 3, , 4, 5)
c = deriv(f1, 3, 4, 5)
d = deriv(f1, 3, h, 4, 5)
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343

2 Answers2

3

No, python applies positional arguments to all named arguments first; h is the third positional argument in the function signature and thus only argument positions 4 and over are captured by *params.

Instead, use a **kwargs argument catching arbitrary keyword arguments and look h up in that:

def deriv(f, x, *params, **kwargs):
    h = kwargs.pop('h', 1.e-9)

You'll now have to name h explicitly when calling deriv:

b = deriv(f1, 3, 4, 5, h=2.0)
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
1

It looks like you're using Python 3, so you can use keyword-only arguments:

>>> def deriv(f, x, *params, h=1.0E-9):
    print(f)
    print(x)
    print(params)
    print(h)

>>> deriv(pow, 'x', 10, 20, 30)
<built-in function pow>
x
(10, 20, 30)
1e-09

>>> deriv(pow, 'x', 10, 20, 30, h=.2)
<built-in function pow>
x
(10, 20, 30)
0.2
Raymond Hettinger
  • 216,523
  • 63
  • 388
  • 485