鱼C论坛

 找回密码
 立即注册
查看: 837|回复: 10

[已解决]闭包问题

[复制链接]
发表于 2020-5-8 16:07:52 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
def func(obj):
    print("func", obj)
    def func1():
        if isinstance(obj, int):
            obj+=1
        elif isinstance(obj, list):
            obj[0] += 1
            print('func1',obj)
    return func1

def func2(obj):
    print("func", obj)
    def func1():
        obj[0] += 1
        print('func1',obj)
    return func1

if __name__ == '__main__':
    mylist = [1,2,3,4,5]
    a=0
    var = func3(mylist)   #这里调用func(mylist)为什么会报错?
    print(';;;')
    var()                 
    var()
    print(mylist)
最佳答案
2020-5-8 16:30:42
本帖最后由 sunrise085 于 2020-5-8 16:32 编辑


这是可变对象与不可变对象的局部作用域使用的问题
可变对象就是 列表、元组、集合、字典等
不可变对象就是数字、字符串等

对于可变对象在函数中使用的时候不必用global关键字指出,但是可变对象若在函数中使用,则必须要用global关键字指出。否则,就会报错。

在 func 函数中,obj 不明确是可变对象还是不可变对象,传进了 func 函数,你在 func1 函数中使用时,需要用global关键字指出,但是你没有写,所以就报错了
在 func2 函数中,obj 明确是可变对象了,传进了 func 函数,你在 func1 函数中就可以直接使用了。这里若是你调用func2的时候传递进去的不是可变对象就会出错了

关于自定义函数调用外部参数的问题
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-5-8 16:11:47 | 显示全部楼层
你没有定义func3啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-8 16:12:40 | 显示全部楼层
写错,是:func2
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-8 16:13:20 | 显示全部楼层
你定义func3了吗??
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-8 16:17:32 | 显示全部楼层

改成func2试试
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-8 16:20:15 | 显示全部楼层
def func(obj):
    print("func", obj)
    def func1():
        if isinstance(obj, int):
            obj+=1
        elif isinstance(obj, list):
            obj[0] += 1
            print('func1',obj)
    return func1

def func2(obj):
    print("func", obj)
    def func1():
        obj[0] += 1
        print('func1',obj)
    return func1

if __name__ == '__main__':
    mylist = [1,2,3,4,5]
    a=0
    var = func(mylist)   #这里会报错,但为什么调用func2(mylist)不会报错?
    print(';;;')
    var()                 
    var()
    print(mylist)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-8 16:30:42 | 显示全部楼层    本楼为最佳答案   
本帖最后由 sunrise085 于 2020-5-8 16:32 编辑


这是可变对象与不可变对象的局部作用域使用的问题
可变对象就是 列表、元组、集合、字典等
不可变对象就是数字、字符串等

对于可变对象在函数中使用的时候不必用global关键字指出,但是可变对象若在函数中使用,则必须要用global关键字指出。否则,就会报错。

在 func 函数中,obj 不明确是可变对象还是不可变对象,传进了 func 函数,你在 func1 函数中使用时,需要用global关键字指出,但是你没有写,所以就报错了
在 func2 函数中,obj 明确是可变对象了,传进了 func 函数,你在 func1 函数中就可以直接使用了。这里若是你调用func2的时候传递进去的不是可变对象就会出错了

关于自定义函数调用外部参数的问题
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-8 18:18:15 | 显示全部楼层
元组是不可变对象。
global  解决的问题是同名问题,比如:局部有a变量,全局也有a变量,当你局部要修改全局变量的时候必须要用global关键字来标注a修改的是全局的。因为python中对于不可变的对象赋值即定义,用global来确认赋值定义的是全局的a对象。
func 和 func2中都指定了obj对象是外部传进来的,这里并没有以上说的变量名问题存在。
按理来说闭包中的函数不应该直接保存了obj对象?我在外边理应是可以引用的呀?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-8 22:14:12 | 显示全部楼层
本帖最后由 Stubborn 于 2020-5-8 22:18 编辑

原因在,05行,obj+=1

如果在一个范围内,对一个变量进行赋值,那么这个变量就会被认为是局部变量,
就像在func的func1这个函数范围之内,我们对obj这个变量进行了重新赋值:obj=obj+1,那么编译器就会认为obj这个变量是一个局部变量,
实际上obj在局部变量(指func1的内部),并未定义,所以需要声明、
而这个赋值表达式实际上是从右向左进行的,也就是说,在进行obj+1运算的时候,obj并没有被定义,所以就爆出了这个UnboundLocalError错误。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-9 09:45:43 | 显示全部楼层
感谢#9和#7  最佳答案不能选两个我就按打的字数多的来算了
obj是属于func函数中的局部对象而非func1中的局部对象,所以对func1来说obj是“非局部变量”,而闭包中要使用“非局部变量”的话就需要用到关键字“nonlocal”来申明。
但是运行时报错位置是:if isinstance(obj, int),这里我只是读取数据还没有去修改对象,按理报错是:obj+=1  这一行。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-9 09:47:37 | 显示全部楼层
附上结果:
def func(obj):
    print("func", obj)
    def func1():
        nonlocal obj
        if isinstance(obj, int):
            obj+=1
        elif isinstance(obj, list):
            obj[0] += 1
            print('func1',obj)
    return func1

def func2(obj):
    print("func", obj)
    def func1():
        obj[0] += 1
        print('func1',obj)
    return func1

if __name__ == '__main__':
    mylist = [1,2,3,4,5]
    a=0
    var = func(a)   #这里会报错,但为什么调用func2(mylist)不会报错?
    print(';;;')
    var()                 
    var()
    print(mylist)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-27 05:40

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表