Reputation: 5760
I'm not sure if this is possible in Python and I was wondering, is there any method for checking at runtime whether a parameter is passed to a Python function without doing some sort of check on the parameter value?
def my_func(req, opt=0):
return was_opt_passed() # Returns bool
print(my_func(0)) # Prints False
print(my_func(0, 0)) # Prints True
This would be superior in some circumstances, if possible, because it relieves the need to remember and check for sentinel values. Is it possible?
Upvotes: 2
Views: 3164
Reputation: 14721
Using decorator
def check_opt_passed(methd):
def m(req, *args, **kwarg):
# this will check even if opt is passed as positional argument
# and check if opt is passed not any other keyword
if args or (kwarg and 'opt' in kwarg):
print('opt is passed')
else:
print('opt is not passed')
return methd(req, *args, **kwarg)
return m
@check_opt_passed
def my_func(req, opt=0):
# dummy expression for testing
return req * opt
print(my_func(1)) # opt is not passed
print(my_func(1, 0)) # opt is passed
print(my_func(1, opt=0)) # opt is passed
Upvotes: 0
Reputation: 12543
A great way would be to use *args or **kwargs.
def was_opt_passed(*args, **kwargs):
return len(args) > 0 or 'opt' in kwargs
def my_func(req, *args, **kwargs):
return was_opt_passed(*args, **kwargs) # Returns bool
print(my_func(0)) # Prints False
print(my_func(0, 0)) # Prints True
print(my_func(0, opt=0)) # Prints True
print(my_func(0, not_opt=0)) # Prints False
*args collects any positional arguments passed to your function that are not already enumerated, while **kwargs collects any keyword arguments passed to your function that are not already enumerated. If args contains a positional argument, we assume it was opt, and it must have been passed. Otherwise, if it is in kwargs, it was passed, and then if we didn't find it in either place, it must not have been passed.
See also https://docs.python.org/3/tutorial/controlflow.html#keyword-arguments
Upvotes: 0
Reputation: 27485
As Mark has already stated in his comment the typical convention is to use the default value None
. Then you can check if it’s still None
upon calling.
def my_func(req, opt=None):
if opt is None:
#opt wasn’t passed.
return False
#opt was passed
return True
Although if you’d like to do more research on other options (most unconventional for most cases) feel free to check out these answers
Upvotes: 1
Reputation: 109
the standard method of detecting if an argument has been passed is sentinel values; however, if you're willing to lose your function signature, you can use **kwargs
:
def my_func(**kwargs):
return 'opt' in kwargs
print(my_func()) #=> False
print(my_func(opt=0)) $=> True
Upvotes: 1
Reputation: 1604
One solution is to use decorators/wrappers. They allow you to interface with what's being passed to your function at runtime and then handle said things as you see fit Consider this code:
def check_keywords(func):
def wrapper(*args, **kwargs):
if kwargs:
print('Keyword was passed!')
return func(*args, **kwargs)
return wrapper
@check_keywords
def my_func(req, opt=0):
print(req)
check_keywords
captures the function and if it detects keywords being passed into my_func
, it then prints something. This print statement can be converted to any arbitrary code you want.
e.g.:
my_func(1)
>>> 1
my_func(1, opt = 1)
>>> Keyword was passed!
>>> 1
Upvotes: 0