【问题标题】:Query on local frame and global frame in python Environment在python环境中查询局部框架和全局框架
【发布时间】:2014-03-30 07:55:51
【问题描述】:

从下面的程序中,我了解到下面环境图中的局部框架(方形)(蓝色框)属于(无非),调用()方法的局部ACTIVATION RECORD类“函数”的对象。这个 'function' 类对象是在我们定义函数 square(x) 时在内部创建的。

我的问题是:

如果上面我的理解是正确的,那么全局框架属于谁(哪个类对象的方法)?

因为,我觉得,控制已经从对象(特定类类型)的某个方法传递到了方。调用(3)方法。

【问题讨论】:

  • 我故意写了 square.__call__(3) 而不是 square(3) 来理解这个问题

标签: python


【解决方案1】:

当一个函数被定义时,它被分配了只读属性func_globals(又名__globals__,自 2.6 起,只有自 3.0 起),它对应于当前模块命名空间(如 module.__dict__ 的视图)。你可以试试,例如:

>>> square.func_globals
# get a big dictionary-like object here

每次函数访问全局变量时都会查询此对象。当您稍后在其他模块中导入此函数时,它仍将引用对其原始范围的引用,并从那里获取全局变量。也就是说,代码:

def square(x):
    return mul(x, x)

大致相同:

def square(x):
    return globals()['mul'](x, x)

def square(x):
    return square.func_globals['mul'](x, x)

因此,一句话:函数的全局变量属于定义它的模块,并通过函数对象的属性访问。

更新

下面发生的事情的更详细的版本(适用于 CPython)。关于 Python 最重要的一点是,与 C 等语言不同,它没有明确区分“声明”和“执行”。当你加载一个模块时,它的代码会被简单地执行。当解释器遇到函数定义时,它会创建函数对象并将其分配给变量。任何已定义或导入模块的内容都将作为全局变量可供函数使用。让我们看一下函数对象:

>>> import dis
>>> dis.dis(square.func_code)  # disassemble the function's bytecode
2           0 LOAD_GLOBAL              0 (mul)
            3 LOAD_FAST                0 (x)
            6 LOAD_FAST                0 (x)
            9 CALL_FUNCTION            2
           12 RETURN_VALUE        
>>> square.func_code.co_names
('mul',)

您可以在开头看到代码LOAD_GLOBAL 0。这意味着:

  1. co_names中找到索引为0的名称,即'mul'
  2. func_globals 中找到名称'mul' 并将其加载到堆栈中
  3. 完成其余的逻辑

【讨论】:

  • bereal 在你的声明中:“函数的全局是模块名称空间”----我不明白“模块名称空间”的含义。 -----截至目前我所知道的是'operator'是一个引用变量指向一个对象(比如OBJ)(类'module'),'mul'是一个引用变量指向一个成员对象(类'function')在那个OBJ(类'module')中。那么,哪个模块在谈论?
  • @Sham 当你说from operator import mul 时,mul 被添加到 current 模块的命名空间中。当您在该模块中定义一个函数时,它还可以通过func_globals 访问该命名空间。所以,我说的是定义函数的模块。当您稍后将该函数导入另一个模块时,它仍然保持对其原始范围的引用。更新了答案。
  • bereal 我想和你聊天,我无法理解“当前模块的命名空间”的含义。你说的是定义函数的模块。但是不清楚当前模块和命名空间的概念?我可以和你聊天吗?
  • >>> from operator import mul >>> def square(x): return mul(x,x) >>> square.__globals__ {'square': , ' builtins': , 'package': None, 'mul': , 'name': 'main', 'doc': None} >>> 我无法理解 square.__globals__ 输出,它在说什么关于?
  • square.__globals__ 包含函数 square 可以访问的全局变量。这意味着,每次字节码解释器遇到LOAD_GLOBAL,它都会探索这个字典以找到对应的变量,如果它没有这样做,就会引发NameError。将尝试更新答案,如果没有帮助将继续聊天。
猜你喜欢
  • 2016-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多