Conditional statements based on function parameter name [duplicate] - python

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to get the original variable name of variable passed to a function
Is there something like below in python where based on the name of the parameter passed to a function we can execute conditional statements like below.
def func(a,b,c,d)
if fourth paramter = d:
#code
elif fourth parameter = e:
#code
else:
#code
def main():
func(a,b,c,d)
func(a,b,c,e)

You should use keyword arguments:
def func(a, b, c, **kwargs):
if 'd' in kwargs:
....
elif 'c' in kwargs:
....
This is not exactly equivalent to what you want, though. If you want to ensure that d or e is the fourth parameter, that would be more troublesome.
Then you could try something like:
def func(a, b, c, d=None, e=None):
if d is not None and e is None:
....
elif e is not None and d is None:
....
Note that this is not exactly what you're asking. It will not access the "original" name of the variable passed to the function as a positional argument, as in the question linked by Stuart. You shouldn't even try to do that, it's pointless.

kwargs will not give you exactly what you want, but it can be close:
def func(a, b, c, **kwargs):
if 'd' in kwargs:
print "do something"
elif 'e' in kwargs:
print "do something else"
def main():
func(a = 1 ,b = 2 ,c = 3, d = 'some_value')
func(a = 1 ,b = 2 ,c = 3, e = 'some_value')

Related

Set default value to variable declared later on? [duplicate]

I'm trying to use
def my_function(a,b)
If I try to print function like this
print(my_function()), when values start from none, I get
"missing 2 required positional arguments"
I want to use default value so when I use, print(my_function()),
a=10 and b=a.
So I tried
def my_function(a=10,b=a)
and I got a not defined.
I don't want to define a before with global.
Is it possible? or something like this
def my_function(a,b)
if a == None:
a = 10
if b == None:
b = a
This didn't work either when I used print(my_function()).
You can set the default to None:
def my_function(a=10, b=None):
if b is None:
b = a
Here the default for a is 10, and b is set to a if left to the default value.
If you need to accept None as well, pick a different, unique default to act as a sentinel. An instance of object() is an oft-used convention:
_sentinel = object()
def my_function(a=10, b=_sentinel):
if b is _sentinel:
b = a
Now you can call my_function(11, None) and b will be set to None, call it without specifying b (e.g. my_function() or my_function(42), and b will be set to whatever a was set to.
Unless a parameter has a default (e.g. is a keyword parameter), they are required.
This function my_function(a,b) expected two positional arguments without default value so It can't be called without them passed
So the main question how can we pass two argument so that second is set to first if not passed
There are two way for this:
kwargs unpacking
def my_function(a=10, **kwargs):
b = kwargs.get('b', a)
sentinel as default Value
_sentinel = object()
def my_function(a=10, b=_sentinel):
if b is _sentinel:
b = a
Hum! I thing you can't define my_function like this. But you can use a decorator to hide the default values computation.
For example:
import functools
def my_decorator(f):
#functools.wraps(f)
def wrapper(a=10, b=None):
if b is None:
b = a
return f(a, b)
return wrapper
You can then define your function like this:
#my_decorator
def my_function(a, b):
return (a, b)
You can use your function with zero, one or two parameters:
>>> print(my_function())
(10, 10)
>>> print(my_function(5))
(5, 5)
>>> print(my_function(5, 12))
(5, 12)

Python dynamic functions with keyword arguments avoid unused parameter

I have a part of code in python, which calls dynamically different functions, where I always want to pass 3 different arguments. However, these functions, might not always need to use those 3 different arguments.
Here is a very simple code that shows the issue:
def test_keyword_args():
def fn1(a, b, c):
return a + b
def fn2(a, b, c):
return a + c
def fn3(a, b, c):
return b + c
obj = {
'a': fn1,
'b': fn2,
'c': fn3,
}
for key in obj:
value = obj[key](a=1, b=2, c=3)
if key == 'a':
assert value == 3
if key == 'b':
assert value == 4
if key == 'c':
assert value == 5
How can I always call same function obj[key](a=1,b=2,c=3) passing this keyword arguments, and avoid complains about unused parameters? (c not used in fn1, b not used in fn2, a not used in fn3)
I can imagine suppressing warnings would do the trick, but I do not think it is the appropriate solution
I am using Python 3.7.3
You can define arguments as keyword only by prefixing the argument list with *, you can then avoid the unused parameter warnings by naming a parameter _. Using **_ allows us to ignore any keyword arguments not in our named parameters
def fn1(*, a, b, **_):
return a + b
def fn2(*, a, c, **_):
return a + c
def fn3(*, b, c, **_):
return b + c
You may use kwargs to pass key word arguments to a function. In such case kwargs is the dictionary with named arguments passed to function.
def fn1(a, b, **kwargs):
return a + b
You can pass anything to this function in format fn1(a_value, b_value, any_parameter_1=100, any_parameter_2=100) etc. In function you receive your variables a and b and also kwargs dictionary with following content
{
"any_parameter_1": 100,
"any_parameter_2": 1000,
}
Also you may pass all variables as kwargs
def fn1(**kwargs):
return kwargs["a"] + kwargs["b"]
But you need to assign names to your parameters like this fn1(a=a_value, b=b_value, any_parameter_1=100, any_parameter_2=100) and kwargs dictionary will looks like
{
"a": a_value,
"b": b_value,
"any_parameter_1": 100,
"any_parameter_2": 1000,
}

Python optional function argument to default to another argument's value

I want to define a function with some optional arguments, let's say A (mandatory) and B (optional). When B is not given, I want it to take the same value as A. How could I do that?
I have tried this, but it doesn't work (name 'B' is not defined):
def foo(A, B=A):
do_something()
I understand that the values of the arguments are not assigned before the body of the function.
You shall do this inside of your function.
Taking your original function:
def foo(A, B=A):
do_something()
try something like:
def foo(A, B=None):
if B is None:
B = A
do_something()
Important thing is, that function default values for function arguments are given at the time, the function is defined.
When you call the function with some value for A, it is too late as the B default value was already assigned and lives in function definition.
You could do it like this. If B has a value of None then assign it from A
def foo(A, B=None):
if B is None:
B = A
print 'A = %r' % A
print 'B = %r' % B

Make function change variables in main code

I want to make a function that does the following:
def func(*args):
for arg in args:
arg+=1
a = 5
b = 6
c = 7
func(a,b,c)
print("%i,%i,%i"%(a,b,c))
I want it to return:
6,7,8
How would I do this?
You can’t! Ta-da.
Python does not support pass-by-reference in any form. Return values instead:
def func(*args):
return [arg + 1 for arg in args]
a = 5
b = 6
c = 7
a, b, c = func(a, b, c)
print("%i,%i,%i" % (a, b, c))
You can't do this, because when you pass in a variable, it takes it in as its value, not as its variable.
Instead, return the value:
def func(*args):
args = list(args)
for i in range(len(args)):
args[i]+=1
return args
a = 5
b = 6
c = 7
a, b, c = func(a,b,c)
print("%i,%i,%i"%(a,b,c))
Which outputs:
>>> print("%i,%i,%i"%(a,b,c))
6,7,8
>>>
You can't, at least not with integer values. Integers are immutable, so you can't change their values, and a function doesn't have access to the namespace of its caller, so you can't rebind the variables (i.e., assign a new value to the variable a outside the function). See this question and various others about what you can and cannot do to affect variables in functions.
If your variables are mutable types like lists, you can achieve a similar effect by mutating the list's value:
def func(*args):
for arg in args:
arg[0] += 1
a = [5]
b = [6]
c = [7]
func(a,b,c)
print("%i,%i,%i"%(a,b,c))
However, you should think about why you want to do this. It may be better to simply return the values and assign them outside the function.
3 posts to tell "You can't" But "Impossible n'est pas français".
Python is the lingua franca of programming languages.
So it's possible:
#!/usr/bin/env python
def func(args):
for i in range(len(args)):
args[i] += 1
abc = [5, 6, 7]
func(abc)
print("%i,%i,%i" % tuple(abc))
actually prints
6,7,8
You can't do it easily because Python doesn't pass immutable objects such as integers by reference. However if you pass the function the names of objects in the current scope, you can achieve your goal like this:
import sys
def func(*args):
namespace = sys._getframe(1).f_globals # caller's globals
for arg in args:
namespace[arg] += 1
a = 5
b = 6
c = 7
func('a','b','c') # note variable *names* passed to function
print("%i,%i,%i" % (a,b,c)) # -> 6,7,8

function default value not defined

I'm trying to use
def my_function(a,b)
If I try to print function like this
print(my_function()), when values start from none, I get
"missing 2 required positional arguments"
I want to use default value so when I use, print(my_function()),
a=10 and b=a.
So I tried
def my_function(a=10,b=a)
and I got a not defined.
I don't want to define a before with global.
Is it possible? or something like this
def my_function(a,b)
if a == None:
a = 10
if b == None:
b = a
This didn't work either when I used print(my_function()).
You can set the default to None:
def my_function(a=10, b=None):
if b is None:
b = a
Here the default for a is 10, and b is set to a if left to the default value.
If you need to accept None as well, pick a different, unique default to act as a sentinel. An instance of object() is an oft-used convention:
_sentinel = object()
def my_function(a=10, b=_sentinel):
if b is _sentinel:
b = a
Now you can call my_function(11, None) and b will be set to None, call it without specifying b (e.g. my_function() or my_function(42), and b will be set to whatever a was set to.
Unless a parameter has a default (e.g. is a keyword parameter), they are required.
This function my_function(a,b) expected two positional arguments without default value so It can't be called without them passed
So the main question how can we pass two argument so that second is set to first if not passed
There are two way for this:
kwargs unpacking
def my_function(a=10, **kwargs):
b = kwargs.get('b', a)
sentinel as default Value
_sentinel = object()
def my_function(a=10, b=_sentinel):
if b is _sentinel:
b = a
Hum! I thing you can't define my_function like this. But you can use a decorator to hide the default values computation.
For example:
import functools
def my_decorator(f):
#functools.wraps(f)
def wrapper(a=10, b=None):
if b is None:
b = a
return f(a, b)
return wrapper
You can then define your function like this:
#my_decorator
def my_function(a, b):
return (a, b)
You can use your function with zero, one or two parameters:
>>> print(my_function())
(10, 10)
>>> print(my_function(5))
(5, 5)
>>> print(my_function(5, 12))
(5, 12)

Categories

Resources