Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在嵌套函数中计算外部作用域中的变量?_Python_Parameters - Fatal编程技术网

Python 如何在嵌套函数中计算外部作用域中的变量?

Python 如何在嵌套函数中计算外部作用域中的变量?,python,parameters,Python,Parameters,代码优先: def another_func(func): func() def outer_func(pa=1, pb=2): def inner_func(): print(pa) print(type(inner_func)) another_func(inner_func) if __name__ == '__main__': outer_func() #print "1" 我不确定“inner_func”是否调用了

代码优先:

def another_func(func):
    func()


def outer_func(pa=1, pb=2):
    def inner_func():
        print(pa)
    print(type(inner_func))
    another_func(inner_func)

if __name__ == '__main__':
    outer_func()
    #print "1"
我不确定“inner_func”是否调用了“outer_func”的参数,但它在“outer_func”的主体中。当被另一个函数调用时,它如何“知道”有一个“pa”


我的意思是,当另一个函数在“outer\u func”中被调用时,实际上传递给它的是什么?Python中的函数对象不仅仅是函数,它们是:1它们携带对执行
def
语句的本地环境的引用

特别是,可以从内部
internal\u func
访问内部
outer\u func
中的局部变量。(即使
返回internal_func
,这些值仍保持活动状态,因此只要
internal_func
处于活动状态,闭包仍将工作。)

如果在
内部函数
中添加
非局部
语句,它甚至可以从
外部函数
的主体中重新分配局部变量


这是怎么回事

嗯,
def
语句2和其他语句一样,只是一个语句。它的作用是这样的:

inner_func = _make_closure(<code from compiling inner_func body>, locals())
internal\u func=\u make\u closure(,locals())
编译内部函数体的代码实际上是一个常量值。编译器在导入时将模块中每个函数体编译成常量对象

但是从
\u make\u closure
返回的函数对象是一个动态创建的新对象,它引用了烘焙到其中的局部变量。每次运行
outer\u func
,它都会从相同的
创建一个新的
internal\u func
闭包,每个闭包捕获当前的本地环境


细节稍微复杂一些,并且在某种程度上,它们在不同的实现中有所不同,因此这将是特定于CPython的

编译器的部分工作是找出函数中每个名称的变量类型。您可能已经阅读了关于全局变量与局部变量的规则(当且仅当您在函数体中的某个位置为名称赋值,并且没有
global
语句时,变量才是局部变量)。但是闭包让事情变得更复杂

  • 如果一个变量本来是局部变量,但是嵌套函数引用该变量而不给它赋值,或者有一个
    非局部
    语句,那么它在外部函数中是一个单元格变量,在内部函数中是一个自由变量。3

  • 当解释器调用一个函数时,它会创建一个
    frame
    对象,该对象包含对函数所有局部变量的引用的局部名称空间

  • 但是单元格变量是特殊的:解释器为每个单元格创建一个特殊的
    cell
    对象,对该单元格的引用进入名称空间,因此每次访问或更改该值时,在该值前面都有一个额外的解引用

  • 上面的
    \u make\u closure
    伪代码所做的是将单元格从外部函数的框架复制到嵌套函数上名为
    \u closure\u
    的特殊属性

  • 然后,当您调用内部函数时,解释器将这些单元格从
    \uuuuu闭包\uuuuuu
    复制到该函数的帧中

  • 因此,外部函数的框架和内部函数的框架都引用相同的单元格,这就是它们共享变量的方式

更多信息,请参阅模块的文档,它向您展示了如何在交互式解释器中查找
\uu closure\uu
co\u freevars
之类的内容,以及让您查看函数编译到的实际字节码的模块


一,。这是其中一个有大量相关但不同含义的词。“闭包”可以指在函数中捕获本地名称空间的技术,也可以指捕获的名称空间,也可以指附加了捕获的名称空间的函数,也可以指捕获的名称空间中的一个变量。通常,从上下文来看,你指的是哪一个是显而易见的。如果不是,你必须说“闭包捕获”或“闭包函数”或“闭包变量”

二,。如果您想知道,
lambda
表达式的工作方式与
def
语句完全相同。和
class
的定义不完全相同,但相似


三,。如果有多层嵌套,实际上会更复杂,但我们忽略这一点。

如果函数与函数对象存在冲突,则代码可能会混淆。读取源文件时,代码对象只计算一次。但是,每次调用
outer\u func
时,都会创建一个名为
internal\u func
的新函数对象。这是因为
def
语句是一种赋值类型:它将函数对象与指定的名称相关联

当然,函数对象包含对其代码的引用,以及对其需要操作的所有名称空间的引用,包括其父级的非本地名称空间和全局模块名称空间


因此,
internal_func
中的
pa
的值将是调用时
outer_func
中的任何值。引用是指向名称空间,而不是名称本身。如果
outer\u func
返回(想想decorators),名称空间将是固定的,并且只能通过
internal\u func
对它的特殊引用来访问。

父范围可以读取的任何变量,内部范围也可以读取。。。然而,编辑这些值会使范围变得不稳定。。。无法替换本地作用域的父变量。。。。内部函数只能编辑局部变量或全局空间中的显式变量