如何使用Python';沙田截流工程

如何使用Python';沙田截流工程,python,scope,namespaces,closures,Python,Scope,Namespaces,Closures,我试图理解闭包在Python中的工作原理,我发现了以下代码片段: def closure(): 计数=0 def inner(): 非局部计数 计数+=1 打印(计数) 返回内部 开始=结束() 开始()#打印1 开始()#打印2 开始()#打印3 我可以理解这段代码,因为当定义内部函数时,封闭范围中有一个名为count的变量,其值为0,内部函数将记住该值 但是,如果我随后将count=0移动到内部函数下面,则代码会变成: def closure(): def inner(): 非局部计数 计

我试图理解闭包在Python中的工作原理,我发现了以下代码片段:

def closure():
计数=0
def inner():
非局部计数
计数+=1
打印(计数)
返回内部
开始=结束()
开始()#打印1
开始()#打印2
开始()#打印3
我可以理解这段代码,因为当定义
内部
函数时,封闭范围中有一个名为count的变量,其值为0,内部函数将
记住该值

但是,如果我随后将
count=0
移动到内部函数下面,则代码会变成:

def closure():
def inner():
非局部计数
计数+=1
打印(计数)
计数=0
返回内部
开始=结束()
开始()#打印1
开始()#打印2
开始()#打印3
令我惊讶的是,代码仍然工作得很好,这让我很困惑。当定义
internal
时,变量
count
不存在于封闭范围内,那么
internal
函数如何能够记住此时名称空间中不存在的值呢


这是因为Python中也存在类似于JS变量的东西吗?

在这两个示例中,您都收到了start变量中的closure方法返回的值,即执行closure方法并返回内部局部方法。因此,count变量也被定义并用值0初始化

当您使用start()调用internal方法时,该方法将被执行,并且在这两种情况下,count变量已经存在

但是如果您有类似这样的代码,那么将出现引用错误

def closure():
    def inner():
        nonlocal count
        count += 1
        print(count)
    inner()
    count = 0

start = closure()
这里在定义计数之前调用内部方法

来自:

如果名称绑定操作发生在代码块内的任何位置,则块内名称的所有使用都将被视为对当前块的引用。如果在绑定前在块内使用名称,则可能会导致错误。这条规则很微妙。Python缺少声明,并且允许名称绑定操作发生在代码块中的任何位置通过扫描代码块的整个文本进行名称绑定操作,可以确定代码块的局部变量。

(我的重点。)


赋值是,只要
count=0
存在于函数中的任何位置,
count
被视为该函数的局部变量,
internal
将引用该变量。(如果在为
count
赋值之前调用
internal()
,您会得到一个异常。)

是的,为了回答OP的另一个问题,没有任何Python像JS或其他语言那样没有代码提升。“由于Python是解释器,它不会编译方法internal,直到调用它为止。”=>错误。。。你确定?或者您的意思是:“在调用
闭包
函数之前,它不会编译函数
内部
”?删除了这一行,因为术语compile既棘手又令人困惑。Python编译发生在整个脚本上,与调用无关,因为它发生在执行/解释阶段。感谢您指出。您的回答意味着名称的作用域在运行时解析。这不是真的,它是在代码运行之前定义的codeobject的一部分。还是我误读了你的解释?不是100%清楚,但这一部分“当你使用start()调用内部方法时,该方法会被执行,到那时,在这两种情况下,count变量已经存在了”,在我看来,执行顺序将决定范围解析。“invoke”对我来说尤其意味着它将发生在运行时,而不是编译期间。