You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中__closure__相关:wrapper内为何无法使用klass变量?

为什么在wrapper函数中使用klass变量会触发UnboundLocalError?

这个问题的核心是Python的变量作用域规则,我来给你拆解清楚:

1. Python如何判定变量的作用域

当你在一个函数内部对某个变量进行赋值操作时,Python会默认把这个变量标记为该函数的局部变量——哪怕外层作用域已经存在同名变量。这时候,函数内部所有对该变量的引用,都会优先指向这个局部变量,而不是外层的变量。

2. 第一段代码的问题分析

看你第一段代码里的wrapper函数:

def wrapper(*args, **kwargs):
    if not klass:  # 这里引用了klass
        klass = type(obj)  # 这里对klass进行了赋值
    return self.func(klass, *args, **kwargs)

因为wrapper里有klass = type(obj)这个赋值操作,Python会把klass认定为wrapper的局部变量。但你在赋值之前,先执行了if not klass:——这时候局部的klass还没有被定义(没有赋值),自然就抛出了UnboundLocalError: local variable 'klass' referenced before assignment。

3. 第二段代码为什么能正常运行

再看修改后的代码:

def __get__(self, obj, klass=None):
    if not klass:
        klass = type(obj)  # 赋值操作在wrapper外面的__get__作用域
    def wrapper(*args, **kwargs):
        return self.func(klass, *args, **kwargs)  # 这里只是引用klass,没有赋值
    return wrapper

这里klass的赋值操作是在__get__方法的作用域里完成的,wrapper函数内部只是引用这个变量,没有任何赋值操作。根据Python的作用域规则,当函数内部没有对变量赋值时,会向上查找外层作用域的同名变量,所以wrapper会正确使用__get__里已经赋值好的klass,不会出现错误。

一个简化的例子辅助理解

你可以试试运行这段代码,会触发和你第一段代码一样的错误:

outer_var = 10
def outer():
    def inner():
        if outer_var > 5:
            outer_var = 20  # 赋值操作让outer_var变成inner的局部变量
        print(outer_var)
    inner()
outer()

而如果把赋值移到inner外面,就能正常运行:

outer_var = 10
def outer():
    if outer_var > 5:
        outer_var = 20
    def inner():
        print(outer_var)
    inner()
outer()

内容的提问来源于stack exchange,提问作者Tide

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 21:28:02