Is it possible to replace the function foo
below with real code such that
def foo():
#calling_scope()['a']=2
def bar(a):
print(a)
foo()
print(a)
bar(1)
prints
1
2
?
To avoid an XY problem, what I really want is to have foo
be part of an external module that summarizes common parsing code. At the moment, I solve the parsing as follows: I have a module parse_args
that contains a bunch of functions such as
def bool(arg):
if arg in [True,'True','true']:
return True
if arg in [False,'False','false']:
return False
raise ValueError('Did not understand boolean value')
def nonnegative(arg):
if arg<0:
raise ValueError('Argument cannot be negative')
return arg
and I do the following in bar
:
def bar(arg1,arg2)
arg1=parse_args.bool(arg1)
arg2=parse_args.nonnegative(arg2)
What I would like to be able to do instead is:
def bar(arg1,arg2)
parse_args(arg1='bool',arg2='nonnegative')
where the pseudocode of parse_args
is
def parse_args(**kwargs)
#cs=calling_scope()
#for arg in kwargs:
# cs[arg]=globals()[kwargs[arg]](cs[arg])
I know this is only marginally less wordy, and I understand that there are probably reasons to favor my current approach over what I aim for, but as someone still learning Python, I am really mainly interested in the feasibility here.
No, it's not possible. You can't alter the local namespace of a function from further down the stack, because the CPython implementation has highly optimised the local namespace in such a way that makes any manipulation impossible.
You are going about your problem the wrong way. Rather than rely on the standard local namespace, create your own in the form of a dictionary. You can then just pass that dictionary around:
def bar(arg1, arg2)
namespace = {'arg1': arg1, 'arg2': arg2}
parse_args(namespace, arg1='bool', arg2='nonnegative')