访问非局部变量

简介: 访问非局部变量

调试库开提供了函数 getupvalue ,该函数允许我们访问一个被 Lua 函数所使用的非局部变量。与局部变量不同,被一个函数所引用的非局部变量即使在引用它的函数已经不活跃的情况下也会一致存在(毕竟这就是闭包的实质)。因此,函数 getupvalue 的第一个参数不是栈层次,而是一个函数(更确切的说,是一个闭包)。函数 getupvalue 的第二个参数是变量索引Lua 语言按照函数引用非局部变量的顺序对他们编号;但由于一个函数不能用同一名称访问两个非局部变量,所以这个顺序是无关紧要的。


我们还可以通过函数 debug.setupvalue 更新非局部变量的值。该函数有三个参数:一个闭包、一个变量索引和一个新值。与函数 setlocal 一样,该函数返回变量名,如果变量索引超出范围则返回 nil


下述示例演示了如何通过变量名访问一个函数中变量的值:

function getvarvalue(name, level, isenv)
  local value
  local found = false
  level = (level or 1) + 1
  -- 尝试局部变量
  for i = 1, math.huge do
    local n, v = debug.getlocal(level, i)
    if not n then break end
    if n == name then
      value = v
      found = true
    end
  end
  if found then return "local", value end
  -- 尝试非局部变量
  local func = debug.getinfo(level, "f").func
  for i =1, math.huge do
    local n, v = debug.getupvalue(func, i)
    if not n then break end
    if n == name then return "upvalue", v end
  end
  if isenv then return "noenv" end        -- 避免循环
  -- 没找到;从环境中获取值
  local _, env = getvarvalue("_ENV", level, true)
  if env then
    return "global", env[name]
  else
    return "noenv"
  end
end


用法如下:

> local a = 4; print(getvarvalue("a"))      --> local   4
> a = "xx"; print(getvarvalue("a"))         --> global  xx


参数 level 指明在那个栈层次中寻找函数, 1 (默认值)意味着直接的调用者。代码中多加的 1 将层次纠正为包括 getvarvalue 自己。


该函数首先查找局部变量。如果有多个局部变量的名称与给定的名称相同,则获取具有最大索引的那个局部变量。因此,函数必须执行完整的循环。如果找不到指定名称的局部变量,那么就查找非局部变量。为了遍历非局部变量,该函数使用 debug.getinfo 函数获取调用闭包,然后遍历非局部变量。最后,如果还是找不到指定名字的非局部变量,就检索全局变量:该函数递归的调用自己来访问合适的 _ENV 变量并在相应环境中查找指定的名字。


参数 isenv 避免了一个诡异的问题。该参数用于说明我们是否处于一个从 _ENV 变量中查询全局名称的递归调用中。一个不使用全局变量的函数可能没有上值 _ENV 。在这种情况下,如果我们试图把 _ENV 当做全局变量来查询,那么由于我们需要 _ENV 来得到其自身的值,所以可能会陷入无限递归循环。因此,当 isenv 为真且函数 getvarvalue 找不到局部变量或上值时, getvarvalue 就不应该再尝试全局变量。

目录
相关文章
|
1月前
初始化局部变量和全局变量
【10月更文挑战第3天】初始化局部变量和全局变量。
36 5
|
3月前
|
存储
全局变量和局部变量在堆和栈的区别
全局变量和局部变量在堆和栈的区别
394 0
|
存储 C语言 Perl
西门子S7-1200的变量如何使用?什么是局部变量和全局变量?临时变量和静态变量有什么区别?
今天给大家讲一下什么是局部变量、全局变量、临时变量、静态变量,这些变量都有什么区别,以及在西门子S7-1200中这些变量如何来使用。
西门子S7-1200的变量如何使用?什么是局部变量和全局变量?临时变量和静态变量有什么区别?
|
C++
39.【C/C++ 全局变量和局部变量 (详解)】
39.【C/C++ 全局变量和局部变量 (详解)】
83 0
|
存储 C语言 C++
函数的内部处理及全局变量和局部变量
函数的内部处理及全局变量和局部变量
124 0
函数的内部处理及全局变量和局部变量
|
存储
局部变量和成员变量的4个区别
定义位置不同、内存中的位置不同、周期不同、初始化不同。
120 0
|
索引
访问局部变量
访问局部变量
100 0
|
开发者 Python
全局变量和局部变量 | 学习笔记
快速学习 全局变量和局部变量
126 0
|
编译器 C语言 开发者
局部变量和全局变量|学习笔记
快速学习局部变量和全局变量
155 0