Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 函数,该函数故意将变量泄漏到调用方';s范围_Python_Variables_Scope_Metaprogramming - Fatal编程技术网

Python 函数,该函数故意将变量泄漏到调用方';s范围

Python 函数,该函数故意将变量泄漏到调用方';s范围,python,variables,scope,metaprogramming,Python,Variables,Scope,Metaprogramming,我有一个函数p()。调用load_variables()应该给出P变量x。 load\u变量应该能够接受默认值作为关键字参数 如何做到这一点 我尝试了以下方法: import inspect def P(): x = 1 load_variables(x = 2) return x def load_variables(**kargs): stack = inspect.stack() try: locals_ = stack[1][0]

我有一个函数
p()
。调用
load_variables()
应该给出
P
变量
x
load\u变量
应该能够接受默认值作为关键字参数

如何做到这一点

我尝试了以下方法:

import inspect
def P():
    x = 1
    load_variables(x = 2)
    return x

def load_variables(**kargs):
    stack = inspect.stack()
    try:
        locals_ = stack[1][0].f_locals
    finally:
        del stack
    for __k, __v in kargs.iteritems():
        locals_[__k] = __v

print P() # => should print 2
x=1
行实际上不应该在那里,因为我想要
load_variables()
x
放在
p
的范围内

有没有其他更好的方法?我想要的是:

  • 变量有一个默认值,例如,在上面调用
    load_Variables()
    时,
    x=2
  • 我可以在
    load\u variables
    中覆盖这些变量,例如,
    load\u varibles()
    可以访问变量字典,如果
    x
    已经在这里,我们会覆盖它,并溢出这个
    x
    ,而不是作为默认参数给出的一个

  • 更新:正如DSM在下面指出的,不支持更新
    locals()
    。所以,答案是不正确的,至少对CPython来说是这样

    您能否使
    load_variables()
    返回一个字典,并使用
    locals()
    更新局部变量:

    请注意,
    x=1
    是必需的,否则字节码编译器将假定
    x
    为全局变量,您将得到
    namererror
    异常
    返回x


    如果你真的想摆脱
    x=1
    ,你可以让我们
    重新运行locals()['x']

    Python编译器和字节码解释器在可能的情况下,将局部变量的引用作为插槽放入定义大小的数组中。这意味着,如果局部变量未在作用域中初始化(分配给),则语言将不知道作用域中存在该变量的插槽,而是在封闭作用域或全局作用域中查找该变量。查看函数的反汇编
    P

    def P():
        load_variables(x=2)
        return x
    
    dis.dis(P)
      2           0 LOAD_GLOBAL              0 (load_variables)
                  3 LOAD_CONST               1 ('x')
                  6 LOAD_CONST               2 (2)
                  9 CALL_FUNCTION          256
                 12 POP_TOP             
    
      3          13 LOAD_GLOBAL              1 (x)
                 16 RETURN_VALUE        
    
    您可以看到,如果不在本地范围内分配
    x
    p
    将在全局范围内查找它

    正确的方法是使用解包明确说明您希望
    load\u variables
    函数返回哪些变量:

    x, y, z = load_variables(...)
    

    既然我们在这里谈论Python,可能有一种方法可以做到这一点,但我想知道:您应该试试吗

    通常,最好定义一个共享存储/值对象,然后将其传递:

    data = {}
    
    def P(data):
         load_variables(data, x=2)
         return data['x']
    
    def load_variables(data, **kargs):
         data.update(kargs)
    

    这样,您就不会有不可预见的副作用。

    不幸的是,这不起作用:您不能以这种方式更新
    本地人
    口述,因为这样的口述是无效的
    P
    在CPython和PyPy中为我返回1,在IronPython中为我返回2,这取决于实现。我如何保证参数的顺序与返回时的顺序相同?例如,像@Mohammad Ali writes一样返回,
    print load_变量(x=2,y=4,z=10)
    作为
    {'y':4,x':2,z':10}
    @MadsOhmLarsen您必须将它们作为
    返回x,y,z
    返回。关键字参数是一个dict,所以它不应该关心顺序,这就是我得到上面混合返回的原因。有没有可能获取它们输入到
    加载变量的顺序,这样我就可以以相同的顺序返回未知数量的关键字参数?@madshomlarsen抱歉,没有,
    **kwargs
    参数没有顺序。您必须将参数作为文本
    加载变量(('x',2),('y',4),('z',10))
    。这就是我所担心的。谢谢。+1“流血”进入更高范围的想法似乎有点血腥
    data = {}
    
    def P(data):
         load_variables(data, x=2)
         return data['x']
    
    def load_variables(data, **kargs):
         data.update(kargs)