nonlocals()在哪里?

Mat*_*ner 4 python variables scope python-3.x python-nonlocal

如何获取当前范围的非局部变量?功能vars,locals并且globals存在,但是有一个功能来获得nonlocals

调用时为什么不列出nonlocals vars

更新

我的问题是,有没有办法来枚举当前范围内都有效的变量,既不varsglobals包括非本地人AFAICT.

我经常使用vars如下代码:

'{meh[0]}/{meh[3]} {a}{b}{c}'.format(**vars())
Run Code Online (Sandbox Code Playgroud)

如果这些变量中的任何变量都在包含函数的范围内,则会失败.

jsb*_*eno 6

从正在运行的代码中,您可以轻松获取非本地变量的名称 - 但是以调用方式重新locals获取内容会使您获得字典变得有点棘手.

使用的nonlocal变量名称存储在co_freevars属性中的当前运行代码对象中.

因此,获取非本地名称是一个问题:

names = inspect.currentframe().f_code.co_freevars

但是,这些变量的内容存储在函数对象__closure__属性(func_closure在Python 2中)中.(不是代码对象).问题在于,如果没有"来自外部的帮助",运行代码就没有简单的方法来获取它正在运行的函数对象.您可以访问链接到代码对象的frame对象,但是没有返回到函数对象的链接.(对于顶级定义的函数,可以显式地使用函数已知名称,如在语句中使用的那样,但是对于封闭的函数,返回给调用者,也无法知道其名称).def

因此,必须采用一种技巧 - 通过使用gc模块(垃圾收集器)获取链接到当前代码对象的所有对象 - 有一个gc.get_referrers调用 - 它将返回链接到代码对象的所有函数对象一个人持有.

因此,在具有非局部变量的函数中,可以执行以下操作:

import inspect, gc

def a(b):
    b1 = 2
    def c():
        nonlocal b1
        print (b)
        code =  inspect.currentframe().f_code  
        names = code.co_freevars
        function = [func for func in gc.get_referrers(code) if isinstance(func, FunctionType)][0]
        nonlocals = dict (zip(names, (x.cell_contents for x in function.__closure__ )))
        print(nonlocals)
        return inspect.currentframe()
    return c

c = a(5)
f = c()
Run Code Online (Sandbox Code Playgroud)

因此检索nonlocals的名称和值.但是如果你有多个该函数的实例(也就是说,如果感兴趣的函数被多次创建多次调用生成它的函数),这将不起作用 - 因为所有这些实例都将链接到相同的代码对象.上面的例子假设只有一个函数与当前代码一起运行 - 并且在这种情况下可以正常工作.对factrory函数的另一个调用将创建另一个函数,可能还有非局部变量的其他值,但是使用相同的代码对象 - function = 上面的列表生成器将检索所有这些,并随意选择其中的第一个.

"正确"函数是当前代码正在执行的函数 - 我试图想出一种检索此信息的方法,但无法实现.如果可以,我将完成此答案,但是现在,这无法帮助您检索非位置值.

(刚刚发现尝试使用带有非局部变量名称的"eval"也不会起作用)

看起来,将当前正在运行的帧与保存非局部变量值的函数对象相关联的唯一事物是在Python解释器的本机端内部的运行时创建的.我无法想到一种方法,在运行时使用ctypes模块查看解释器数据结构,这当然不适用于任何实际的生产代码.

底线:您可以可靠地检索非本地变量名称.但看起来你不能得到他们的价值,因为他们的名字是一个字符串(也不是重新绑定).

您可以尝试在Python的bug跟踪器或Python-ideas邮件列表上打开"nonlocals"调用的功能请求.