773254968 发表于 2020-5-8 16:07:52

闭包问题

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

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

if __name__ == '__main__':
    mylist =
    a=0
    var = func3(mylist)   #这里调用func(mylist)为什么会报错?
    print(';;;')
    var()               
    var()
    print(mylist)

wuqramy 发表于 2020-5-8 16:11:47

你没有定义func3啊

773254968 发表于 2020-5-8 16:12:40

写错,是:func2

qiuyouzhi 发表于 2020-5-8 16:13:20

你定义func3了吗??

wuqramy 发表于 2020-5-8 16:17:32

773254968 发表于 2020-5-8 16:12
写错,是:func2

改成func2试试

773254968 发表于 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 += 1
            print('func1',obj)
    return func1

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

if __name__ == '__main__':
    mylist =
    a=0
    var = func(mylist)   #这里会报错,但为什么调用func2(mylist)不会报错?
    print(';;;')
    var()               
    var()
    print(mylist)

sunrise085 发表于 2020-5-8 16:30:42

本帖最后由 sunrise085 于 2020-5-8 16:32 编辑

773254968 发表于 2020-5-8 16:20


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

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

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

关于自定义函数调用外部参数的问题

773254968 发表于 2020-5-8 18:18:15

元组是不可变对象。
global解决的问题是同名问题,比如:局部有a变量,全局也有a变量,当你局部要修改全局变量的时候必须要用global关键字来标注a修改的是全局的。因为python中对于不可变的对象赋值即定义,用global来确认赋值定义的是全局的a对象。
func 和 func2中都指定了obj对象是外部传进来的,这里并没有以上说的变量名问题存在。
按理来说闭包中的函数不应该直接保存了obj对象?我在外边理应是可以引用的呀?

Stubborn 发表于 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错误。

773254968 发表于 2020-5-9 09:45:43

感谢#9和#7最佳答案不能选两个{:10_266:}我就按打的字数多的来算了{:10_257:}
obj是属于func函数中的局部对象而非func1中的局部对象,所以对func1来说obj是“非局部变量”,而闭包中要使用“非局部变量”的话就需要用到关键字“nonlocal”来申明。
但是运行时报错位置是:if isinstance(obj, int),这里我只是读取数据还没有去修改对象,按理报错是:obj+=1这一行。

773254968 发表于 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 += 1
            print('func1',obj)
    return func1

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

if __name__ == '__main__':
    mylist =
    a=0
    var = func(a)   #这里会报错,但为什么调用func2(mylist)不会报错?
    print(';;;')
    var()               
    var()
    print(mylist)
页: [1]
查看完整版本: 闭包问题