Using Default Arguments in a Function

C default arguments

Not really. The only way would be to write a varargs function and manually fill in default values for arguments which the caller doesn't pass.

Python: explicitly use default arguments

Unfortunately there is no such feature in Python. There are hackarounds, but they're not very likable.

The simple and popular pattern is to move the default into the function body:

def function(arg=None):
if arg is None:
arg = 'default'
...

Now you can either omit the argument or pass arg=None explicitly to take on the default value.

Using Default Arguments in a Function

I would propose changing the function declaration as follows so you can do what you want:

function foo($blah, $x = null, $y = null) {
if (null === $x) {
$x = "some value";
}

if (null === $y) {
$y = "some other value";
}

code here!

}

This way, you can make a call like foo('blah', null, 'non-default y value'); and have it work as you want, where the second parameter $x still gets its default value.

With this method, passing a null value means you want the default value for one parameter when you want to override the default value for a parameter that comes after it.

As stated in other answers,

default parameters only work as the last arguments to the function.
If you want to declare the default values in the function definition,
there is no way to omit one parameter and override one following it.

If I have a method that can accept varying numbers of parameters, and parameters of varying types, I often declare the function similar to the answer shown by Ryan P.

Here is another example (this doesn't answer your question, but is hopefully informative:

public function __construct($params = null)
{
if ($params instanceof SOMETHING) {
// single parameter, of object type SOMETHING
} elseif (is_string($params)) {
// single argument given as string
} elseif (is_array($params)) {
// params could be an array of properties like array('x' => 'x1', 'y' => 'y1')
} elseif (func_num_args() == 3) {
$args = func_get_args();

// 3 parameters passed
} elseif (func_num_args() == 5) {
$args = func_get_args();
// 5 parameters passed
} else {
throw new \InvalidArgumentException("Could not figure out parameters!");
}
}

Default arguments in a function when using decorators

In this case **kwargs is not about the function signature, it's about how you called it.
And your call

simple(10)

have only specified one positional argument.

Decorator (wrapper) knows nothing about the function and its default arguments.
It just passes the arguments it received further.

simple(*(10,), **{})

If you want to do some excercise and write decorator that is informed about the defaults of a function it is wrapping, I suggest to take a look at inspect.signature().

How to tell a function to use the default argument values?

One way to do it would be with variadic argument unpacking:

def foo(..., **kwargs):
...
if math.isclose(x, y, **kwargs):
...

This would allow you to specify atol and rtol as keyword arguments to the main function foo, which it would then pass on unchanged to math.isclose.

However, I would also say that it is idiomatic that arguments passed to kwargs modify the behaviour of a function in some way other than to be merely passed to sub-functions being called. Therefore, I would suggest that instead, a parameter is named such that it is clear that it will be unpacked and passed unchanged to a sub-function:

def foo(..., isclose_kwargs={}):
...
if math.isclose(x, y, **isclose_kwargs):
...

You can see an equivalent pattern in matplotlib (example: plt.subplots - subplot_kw and gridspec_kw, with all other keyword arguments being passed to the Figure constructor as **fig_kw) and seaborn (example: FacetGrid - subplot_kws, gridspec_kws).

This is particularly apparent when there are mutiple sub-functions you might want to pass keyword arguments, but retain the default behaviour otherwise:

def foo(..., f1_kwargs={}, f2_kwargs={}, f3_kwargs={}):
...
f1(**f1_kwargs)
...
f2(**f2_kwargs)
...
f3(**f3_kwargs)
...

Caveat:

Note that default arguments are only instantiated once, so you should not modify the empty dicts in your function. If there is a need to, you should instead use None as the default argument and instantiate a new empty dict each time the function is run:

def foo(..., isclose_kwargs=None):
if isclose_kwargs is None:
isclose_kwargs = {}
...
if math.isclose(x, y, **isclose_kwargs):
...

My preference is to avoid this where you know what you're doing since it is more brief, and in general I don't like rebinding variables. However, it is definitely a valid idiom, and it can be safer.

Function default argument value depending on argument name in C++

According to the C++17 standard (11.3.6 Default arguments)

9 A default argument is evaluated each time the function is called
with no argument for the corresponding parameter. A parameter shall
not appear as a potentially-evaluated expression in a default
argument.
Parameters of a function declared before a default
argument are in scope and can hide namespace and class member name

It provides the following example:

int h(int a, int b = sizeof(a)); // OK, unevaluated operand

So, this function declaration

void f(int y = sizeof(y)) {}

is correct because, in this expression sizeof(y), y is not an evaluated operand, based on C++17 8.3.3 Sizeof:

1 The sizeof operator yields the number of bytes in the object
representation of its operand. The operand is either an expression,
which is an unevaluated operand
(Clause 8), or a parenthesized
type-id.

and C++17 6.3.2 Point of declaration:

1 The point of declaration for a name is immediately after its
complete declarator (Clause 11) and before its initializer (if any),
except as noted below.

How to call a function with default parameter through a pointer to function that is the return of another function?

Defaulted arguments are a bit of C++ syntactic sugar; when calling the function directly with insufficient arguments, the compiler inserts the default as if the caller had passed it explicitly, so the function is still called with the full complement of arguments (Mult(4) is compiled into the same code as Mult(4, 2) in this case).

The default isn't actually part of the function type though, so you can't use the default for an indirect call; the syntactic sugar breaks down there, since as soon as you are calling through a pointer, the information about the defaults is lost.



Related Topics



Leave a reply



Submit