gpt4 book ai didi

python - nonlocals() 在哪里?

转载 作者:太空狗 更新时间:2023-10-30 02:34:17 27 4
gpt4 key购买 nike

如何获取当前作用域的非局部变量?函数 varslocalsglobals 存在,但是是否有获取 nonlocals 的函数?

为什么在调用 vars 时没有列出非本地人?

更新

我的问题是无法枚举当前范围内可用的变量,因为 varsglobals 都不包含非本地 AFAICT。

我经常在如下代码中使用 vars:

'{meh[0]}/{meh[3]} {a}{b}{c}'.format(**vars())

如果这些变量中的任何一个在包含函数的范围内,则失败。

最佳答案

从运行的代码中,您可以轻松获取非局部变量的名称 - 但是以调用 locals 的方式检索它们的内容让您获得字典有点棘手。

使用的非本地变量名称存储在当前运行的代码对象中,在 co_freevars 属性中。

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

names = inspect.currentframe().f_code.co_freevars

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

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

因此,在一个带有非局部变量的函数中,我们可以这样做:

import inspect, gc

from types import FunctionType

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()

因此检索非本地人的名称和值。 但是如果您周围有该函数的多个实例,这将不起作用(也就是说,如果感兴趣的函数是通过多次调用生成它的函数多次创建的) - 因为所有这些实例都将链接到相同 代码对象。上面的例子假设只有一个函数在当前代码中运行——并且在这种情况下会正常工作。对 factory 函数的另一个调用将创建另一个函数,可能具有非局部变量的其他值,但具有相同的代码对象 - 上面的 function = 列表生成器将检索所有这些,并任意选择首先。

“正确”函数是当前代码正在其上执行的函数 - 我正在尝试想出一种检索此信息的方法,但无法实现。如果可以的话,我会完成这个答案,但目前,这无法帮助您检索非本地值值。

(刚刚发现尝试将“eval”与非局部变量名称一起使用也不会奏效)

看起来唯一将当前运行的框架链接到保存非局部变量值的函数对象的东西是在运行时在 Python 解释器的 native 端创建的。除了使用 ctypes 模块在运行时查看解释器数据结构之外,我想不出一种方法,这当然不适合任何实际的生产代码。

底线:您可以可靠地检索非局部变量名称。但看起来您无法将其名称作为字符串来获取它们的值(然后也无法重新绑定(bind))。

您可以尝试在 Python 的错误跟踪器或 Python-ideas 邮件列表上打开“非本地”调用的功能请求。

关于python - nonlocals() 在哪里?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8968407/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com