从下面的程序中,我了解下面环境图中的本地框架(方形)(蓝色框)属于(除了),调用的本地激活记录()方法类'function'的对象。当我们定义函数square(x)时,会在内部创建这个'function'类对象。
我的问题是:
如果我的理解在上面是正确的,那么全局框架对谁(哪个类对象的方法)属于?
因为,我觉得,控件已从对象的某个方法(特定类类型)传递到方形。调用(3)方法。
答案 0 :(得分:2)
当定义一个函数时,它被赋予了只读属性func_globals
(自2.6以来的__globals__
以及仅3.0之后的那个),它对应于当前模块名称空间(如{{ {1}})。您可以尝试,例如:
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)
因此,在一个句子中:函数的全局变量属于定义它的模块,并通过函数对象的属性进行访问。
<强>更新强>
下面发生的更详细的版本(适用于CPython)。理解Python的最重要的事情是,与C等不同,它在“声明”和“执行”之间没有明确的区别。加载模块时,只需执行其代码即可。当解释器遇到函数定义时,它会创建函数对象并将其分配给变量。无论已定义或导入到模块中的任何内容都将作为全局变量用于该函数。让我们看一下函数对象:
def square(x):
return square.func_globals['mul'](x, x)
您可以在开头看到代码>>> 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
中找到包含0
索引的名称,即co_names
'mul'
中找到名称'mul'
并将其加载到堆栈