Python:在调用scop时修改变量绑定

2024-04-20 09:05:30 发布

您现在位置:Python中文网/ 问答频道 /正文

有没有可能用实际代码替换下面的函数foo,以便

def foo():
    #calling_scope()['a']=2
def bar(a):
    print(a)
    foo()
    print(a)
bar(1)

印刷品

1
2

什么?你知道吗


为了避免XY问题,我真正想要的是让foo成为总结常见解析代码的外部模块的一部分。目前,我按如下方式解决解析:我有一个模块parse_args,其中包含一组函数,例如

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  

我在bar中执行以下操作:

def bar(arg1,arg2)
    arg1=parse_args.bool(arg1)
    arg2=parse_args.nonnegative(arg2)

我想做的是:

def bar(arg1,arg2)
    parse_args(arg1='bool',arg2='nonnegative')

其中parse_args的伪码是

def parse_args(**kwargs)
    #cs=calling_scope()
    #for arg in kwargs:
    #    cs[arg]=globals()[kwargs[arg]](cs[arg])

我知道这只是稍微少了点罗嗦,而且我理解可能有理由支持我目前的方法而不是我的目标,但是作为一个仍在学习Python的人,我真正感兴趣的是这里的可行性。你知道吗


Tags: infalsetruereturniffooparsedef
2条回答

不,不可能。不能从堆栈的更底层更改函数的本地名称空间,因为CPython实现已经高度优化了本地名称空间,使得任何操作都不可能。你知道吗

你的问题处理得不对。与其依赖于标准的本地名称空间,不如以字典的形式创建自己的名称空间。你可以把字典传给别人:

def bar(arg1, arg2)
    namespace = {'arg1': arg1, 'arg2': arg2}
    parse_args(namespace, arg1='bool', arg2='nonnegative')

我找到了一种方法,使用函数注释和装饰器,以比我希望的更漂亮的方式来完成我想要的解析。(实际上,这实际上修改了我希望修改的函数中的变量绑定,从技术上讲,这是可能的,因为通过使用decorators,调用者变成了被调用者。)

我现在写信

@validated()
def f(a:'nonnegative integer',b:'bool|function', c:'float in_range(0,1)', d:'{float}', e:'{integer:any}',f:'bool'):  
    print(a,b,c,d,e,f)

然后得到

>>f(a=2,b=lambda x: x>2, c=0,d=[1.2, 2.3], e={1:'foo',2:'bar'},f='true')
2 <function <lambda> at 0x7f4779ae8400> 0.0 [1.2, 2.3] {1: 'foo', 2: 'bar'} True

请注意,整数参数c=0转换为float0.0,字符串'true'转换为boolTrue。注释中的大括号表示任何iterable,冒号表示字典。竖线表示备选方案。不同的需求可以用空格连接起来,就像参数ac一样。如果不符合任何规范,例如a=-1,则抛出一个有充分根据的错误:

swutil.validation.ValidationError: Invalid argument for parameter 'a': -1 was rejected by 'nonnegative integer' (-1 was rejected by 'nonnegative')

最后,decorator接受可用于指定必须传递哪些参数的参数。例如,@validated('a^b')@validated('a|b')指定必须传递ab中的一个。另一个将用NotPassed实例填充。你知道吗

如果有人对代码感兴趣,请留下评论,我将与大家分享。你知道吗

相关问题 更多 >