I'm defining a function with some kwargs
. I know having an undefined variable as a kwarg
default value throws an error. For example:
# This is fine
def foo(word='Ni!'):
print(word)
foo()
> Ni!
# This won't work
def foo(word=it):
print(word)
it = 'Ni!'
foo()
> (gives an error)
But is there some way to use the keyword of a kwarg
itself as the default value variable name, with the expectation that it will have been defined by the time the function is called?
# This is what I want
def foo(word=word):
print(word)
word = 'Ni!' # Note it's defined after function definition, but before function call
foo()
> Ni!
(I'm having trouble searching for answers to this, apologies if it's answered somewhere already!)
CodePudding user response:
Using a global would be an option. But I think using function attributes gives a more clean solution:
def foo(word=None): # use 'None' as sentinel
if word is not None:
print(word)
else: # get the current default value from a function attribute
print(getattr(foo, 'default_word', 'default'))
foo() # use default first time
foo.default_word = 'changed default' # change the default
foo() # gets the new default
foo('hi') # use argument
Result:
default
changed default
hi
CodePudding user response:
But is there some way to use the keyword of a kwarg itself as the default value variable name, with the expectation that it will have been defined by the time the function is called?
The short answer here is no, what you are trying to do isn't possible in this exact way. This is because the default value must be known at the time of the def
when the interpreter sets the function name to the value of the function object.
CodePudding user response:
Decorator is a possible option:
from functools import wraps
def kwd_load_globals(**kwd2name):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
f_globals = func.__globals__
for kwd in kwd2name.keys() - kwargs.keys():
try:
kwargs[kwd] = f_globals[kwd2name[kwd]]
except KeyError:
pass
return func(*args, **kwargs)
return wrapper
return decorator
@kwd_load_globals(word='word')
def foo(word):
print(word)
word = 1
foo() # 1