阅读Python中父级作用域

12

假设我有一层层的函数,我想要能够访问 (但不改变!) 父级作用域。以下是一个说明性的例子。

def f():
    a = 2
    b = 1
    def g():
        b = 2
        c = 1
        print globals() #contains a=1 and d=4
        print locals() #contains b=2 and c=1, but no a
        print dict(globals(), **locals()) #contains a=1, d=4 (from the globals), b=2 and c=1 (from g)
        # I want a=2 and b=1 (from f), d=4 (from globals) and no c
    g()
a = 1
d = 4
f()

我可以从 g 中访问 f 的作用域吗?


你就在那里有示例代码,可以试一下。 - Waleed Khan
我认为这对你会很有趣: http://ynniv.com/blog/2007/08/closures-in-python.html - fuaaark
@arxanas 我所提供的示例代码并没有解决这个问题,但它确实说明了问题,可以看第10行。 - Andy Hayden
1
请注意,f()的本地变量也包括函数g - Sven Marnach
1个回答

9
一般来说,在Python中无法做到。如果你的Python实现支持堆栈帧(CPython支持),你可以使用inspect模块检查调用函数的帧并提取局部变量,但我怀疑这不是解决你想解决的问题的最佳方法(无论那是什么)。如果你认为需要这样做,那么你的设计可能存在某些缺陷。
请注意,使用inspect将使您进入调用栈而不是词法范围堆栈。如果你从f()返回g,f的作用域将消失,所以根本没有办法访问它,因为它甚至不存在。

7
@hayden: 不,这不是出于安全原因。就像我说的那样,如果您的Python实现支持堆栈帧,您可以向上遍历调用堆栈,只需执行类似inspect.currentframe().f_back.f_locals的操作即可获取调用帧的本地变量,这将是您示例中的f的一个实例。您无法访问词汇作用域中的变量是因为这个概念没有意义。调用堆栈中可能有多个f的实例,每个实例都具有不同的本地变量,或者根本没有任何实例。 - Sven Marnach
1
不应该做这样的事情的原因在于,它与具有词法作用域而非动态作用域(也就是几乎任何编程语言)的编程语言的精神相悖。请参见http://en.wikipedia.org/wiki/Dynamic_scoping#Lexical_scoping_and_dynamic_scoping以了解更多详情。 - Sven Marnach
@hayden:除非使用堆栈帧内省,否则g()无法访问fb,因为它被gb隐藏。一旦您实际上关闭了f的某些名称,它们将附加到闭包中,因此您可以通过内省访问它们。但是,您的代码实际上没有访问f的任何名称,因此它不会产生闭包。 - Sven Marnach
啊哈!那就是我缺失的部分(它们只有在被查找后才会被附加)。如果我们可以遍历所有“可能”的变量,那么我们就完成了……但我们不知道它们是什么!:( - Andy Hayden
如果在函数f中定义了f_local_state = locals().keys(),那么在函数g中,你可以迭代f的作用域,因为你可以在g中访问f_local_state - AmourK
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接