Default value for optional parameter - python

I'm making a function in python that takes an optional parameter *args. This function calls upon another function passing this optional parameter as well. However, when a certain condition applies, I want the optional parameter to have a certain default value, rather than the value passed in the function call. It is clear in the snippet of code below that simply setting a new value for *args is incorrect, but what is the correct method of doing this?
def function(arg1, arg2, *args):
if condition:
*args = value
function2(*args)

You could identify your parameter by index in args:
def function(arg1, arg2, *args):
if condition:
args = list(args)
if len(args) == 0: # the second arg in args was not set
args.append("first default")
if len(args) == 1:
args.append("second default")
function2(*args)
But as you see - it's a little ugly. It will involve a lot of if statements in case you want to use a lot of default positional arguments. Use **kwargs if you can.

Apparantly *args is a list, so I had to assign it as args = [value], instead of *args = value. That way it solved the problem.

Related

Passing same argument names for a function in Python

In python, I have a class with functions printing certain outputs, of which each has default parameters but those can be changed, like
def func1(self,a='a', b='b'):
return something
def func2(self,c='c', d='d'):
return something
Lots of other functions of a similar kind too.
I created another function that can take those functions with parameters and can do something with them, ie
def foo(self, default,*args,**kwargs):
df=self.df
if default == True:
args = self.list1
else:
for fname in args:
getattr(self, fname)(*kwargs)
df['appending_array'] = df.apply(lambda...
In the effect I'd like to be able to call something like
object.foo(False, func2,func11,d='z')
Unfortunately in the loop, when I change d to 'z', it changes the first argument of each function that is iterated, instead of the actual parameter d from the function I want.
Is there a possibility to either rearrange it so I can pass the original parameters of each passed function, or configure **kwarg so it can refer to the original parameters' names of each function?
Many thanks for any help/advice
So, if I understand correctly, you want to write it such that if, for example, d is present in the foo call, it is solely passed to all functions in args that have d as an input argument (in this case, func2)?
If so, then you want to determine all input arguments that each function can take.
Luckily, Python has a function that allows you to do just that: inspect.signature.
So, you could rewrite it like this (I am assuming you wanted to pass the names of the functions as args, not the actual functions themselves):
from inspect import signature
def foo(self, default, *args, **kwargs):
df=self.df
if default:
args = self.list1
else:
for fname in args:
# Obtain function
func = getattr(self, fname)
# Obtain signature of this function
f_sig = signature(func)
# Create dict with values for this function, updating with values from kwargs
# Make sure to skip 'self'
f_kwargs = {argname: kwargs.get(argname, argpar.default)
for argname, argpar in f_sig.parameters.items()
if (argname != 'self')}
# Call this function
f_out = func(**f_kwargs)
# Perform some operations on the output of this function
df['appending_array'] = df.apply(lambda...
Keep in mind that this only works if every function that is ever passed as args solely takes optional arguments.
If one argument is mandatory, it must be passed to kwargs.
PS: I am however unsure what the use of the args = self.list1 for if default is.
Because that part is incompatible with everything else.
You need to unpack the kwargs with dictionary unpacking using two stars:
getattr(self, fname)(**kwargs)
And I think you also need to provide self as the first argument since these are unbound methods:
getattr(self, fname)(self,**kwargs)

Using the = sign in variables for method calls

When doing a method call in Python, in which cases do you use the = sign when entering arguments?
I noticed sometimes it's:
object.method(argument1 = ... , argument2 = ...)
and other times it's
object.method(... , ...)
Thanks in advance!
That types of arguments are called keyword arguments, probably you've seen that as (kwargs).
In a function you can pass 2 types of args, positional arguments and keyword-arguments.
def function(arg):
So you have to pass inside this function a positional argument, this means that you have to pass only the value for that arg like
function(1) or maybe a string function("hello") or maybe a list and so on; This type of arg is called position arg.
When you have to specify the name of the variable inside the brackets of a function call like function(name = "John"), you are using the keyword args.
If you want to understand more on this topic, i suggest you to see the unpack operator in Python (*) and then *args and **kwargs.
2 words to say what *args and **kwargs do in Python, they allows you to specify an unlimited number of arguments inside a function call.
def function(*args, **kwargs):
pass
function(1,2,3,"hello",[1,2,3],name="John",age=5)

Default argument with *args

I am new to python and currently learning about functions in python
I created a function which takes all type of argument (normal, *args, default argument, **kwargs)
def func (a, *args, b=3, **kwargs):
print(a)
print(args)
print(b)
print(kwargs)
And to call the fuction i used
func (1, 3,5,4, 5, a=5,j=6)
But default argument value remains same and i don't know how to pass a different value to default parameter 'b'
How can i pass new values to default parameter 'b' in above function??
The parameter *args is your issue.
The special syntax *args in function definitions in python is used to pass a variable number of arguments to a function. It is used to pass a non-key worded, variable-length argument list.
So *args takes all the parameters (since it expects a variable-length list), and b will never receive them. You need to remove *args.

Function parameters, list and int in python

i'm trying to write a function that takes a list and a int as its arguments.
functionName(*args, number)
#do stuff
number needs to be an int but i keep getting a syntax error in IDLE (that's the IDE i'm using)
If your first argument is to be a list, remove the *:
def functionName(listob, number):
The *args syntax is used to catch an arbitrary number of positional arguments and must be listed after all other positional (and keyword) arguments:
def functionName(number, *args):
because it allows your function to be called with just the number, or with any number of extra arguments; functionName(42, 'foo', 'bar') results in number = 42 and args = ('foo', 'bar'). That's not the same as passing in a list object however.
Python doesn't otherwise constrain the types of objects that can be passed in; *args would present extra arguments to your function as a tuple, but only because that's the best way to represent 0 or more arguments extra passed into your function.
You cannot have *args before an actual argument. So you can call it like this:
def foo(name, *args)
However, you want a list, so there's no need for *args. Having the following signature will do just fine:
def foo(name, lst)

How does argparse's add_argument take variable length arguments before keyword arguments?

In python2.7, the argparse module has an add_argument method which can take a variable number of unnamed arguments before its keyword arguments as shown below:
parser = argparse.ArgumentParser(description='D')
parser.add_argument('-a', '-b', ... '-n', action='store', ... <other keyword args>)
As far as I know, function definitions as follow don't work:
def fxn(var_args*, action, otherstuff):
def fxn(action, otherstuff, var_args*): # results in conflict on action
What is the proper means to emulate the add_argument behaviour?
Python's argument definition order is...
Required and/or default-value arguments (if any)
variable-length positional arguments placeholder (*<name> if desired)
keyword arguments placeholder (**<name> if desired)
The positional arguments placeholder gets a list, the keyword arguments placeholder gets a dict.
add_arguments simply looks for keys in the dict of keyword arguments, rather than spelling out all of the possible arguments in the declaration. Something along the lines of...
def add_arguments(*posargs, **kwargs):
if 'action' in kwargs:
# do something
You can pass arbitrary number of arguments to a function.
Here is an example
def f(x, *args, **kwargs):
print x
for arg in args:
print arg
for key, value in kwargs:
print key + ': ' + value
Reading this will help: http://docs.python.org/tutorial/controlflow.html#keyword-arguments.

Categories