Can I call function in python with named arguments as a variable?
Question:
For example
username_type = 'email'
def get_user_by(email=None, username=None):
if email:
return user.get_by_email(email)
elif username:
return user.get_by_username(username)
get_user_by(username_type = username)
Of course this line won’t work
get_user_by(username_type = username)
But I want something like this to make it work
I don’t know which type will I get the user from but I want the named argument based on variable
Answers:
You can pass a dictionary of keywords arguments to a function using the **
operator. The keys of the dictionary are the parameter names in the function.
In this case, that could be:
get_user_by(**{username_type: username})
If the variable username_type
has the value 'email'
then the username would be received in get_user_by
as the keyword argument email
.
I think the OP could use a little more detail. The * and ** notation are used to pack and unpack in python, * to pack and unpack a list and ** to pack and unpack a dictionary. For example,
[1,2,3,*[4,5,6]] #The inside list will be unpacked into the overall list.
{'a':1,'b':2, **dict(z=7,w=8)} #The dictionary will be unpacked into the outside dictionary.
This also works with function calls and definitions.
def f(*args): #pack all args into a list called args.
return args
print(f(1,2,3))
y = [1,2,3]
f(*y) #Unpack y into f, same as f(1,2,3)
def f(**kargs): #pack all keyword-args into a dictionary called kargs.
return kargs.get('thing',None)
print(f(x=7))
print(f(thing=7))
If one needs a more generalized solution, both for positional and named arguments, one should replace the line
get_user_by(username_type = username)
with a decorator-like code:
def args_passer(args, kwargs):
def out():
return get_user_by(*args, **kwargs)
return out()
args_passer([], {username_type: username})
For example
username_type = 'email'
def get_user_by(email=None, username=None):
if email:
return user.get_by_email(email)
elif username:
return user.get_by_username(username)
get_user_by(username_type = username)
Of course this line won’t work
get_user_by(username_type = username)
But I want something like this to make it work
I don’t know which type will I get the user from but I want the named argument based on variable
You can pass a dictionary of keywords arguments to a function using the **
operator. The keys of the dictionary are the parameter names in the function.
In this case, that could be:
get_user_by(**{username_type: username})
If the variable username_type
has the value 'email'
then the username would be received in get_user_by
as the keyword argument email
.
I think the OP could use a little more detail. The * and ** notation are used to pack and unpack in python, * to pack and unpack a list and ** to pack and unpack a dictionary. For example,
[1,2,3,*[4,5,6]] #The inside list will be unpacked into the overall list.
{'a':1,'b':2, **dict(z=7,w=8)} #The dictionary will be unpacked into the outside dictionary.
This also works with function calls and definitions.
def f(*args): #pack all args into a list called args.
return args
print(f(1,2,3))
y = [1,2,3]
f(*y) #Unpack y into f, same as f(1,2,3)
def f(**kargs): #pack all keyword-args into a dictionary called kargs.
return kargs.get('thing',None)
print(f(x=7))
print(f(thing=7))
If one needs a more generalized solution, both for positional and named arguments, one should replace the line
get_user_by(username_type = username)
with a decorator-like code:
def args_passer(args, kwargs):
def out():
return get_user_by(*args, **kwargs)
return out()
args_passer([], {username_type: username})