Python中不使用全局变量与返回值,如何使父函数变量被子函数赋值后生效?
Python中不使用全局变量与返回值,如何使父函数变量被子函数赋值后生效?
嘿,这个问题在Python嵌套函数结合GUI回调的场景里挺常见的~咱们先拆解下你代码里的问题:你在subfunction里写的var = 22,其实是创建了一个属于subfunction自己的局部变量,和外层function里定义的var完全是两个独立的东西,所以外层的var始终是99,最后打印出来自然不是你想要的22。
这里给你两种不用全局变量、也不用返回值的解决方法:
方法一:使用nonlocal关键字(Python 3+适用)
nonlocal是Python 3专门为嵌套函数设计的关键字,它可以告诉Python:当前函数里的这个变量,不是自己的局部变量,而是来自上一层嵌套函数的局部变量。这样赋值时就会直接修改外层的变量,而不是新建一个。
修改后的代码如下:
import tkinter as tk def function(): def subfunction(): nonlocal var # 声明该变量来自外层function的局部作用域 var = 22 print('subfunction', var) top.destroy() var = 99 top = tk.Toplevel(root) top.title('top level') tk.Button(top, text='Button toplevel', command=subfunction).pack() root.wait_window(top) print('function', var) # 现在会输出22啦 var = 0 root = tk.Tk() print(var) tk.Button(root, text='Button', command=function).pack() root.mainloop()
方法二:用可变对象包装变量(兼容Python 2和3)
如果需要兼容Python 2,或者不想用nonlocal关键字,可以用可变对象(比如列表、字典)来包装你的变量。因为可变对象的内容修改后,引用它的地方都会看到变化,不需要额外关键字。
比如用列表包装var:
import tkinter as tk def function(): var = [99] # 把变量放进列表里 def subfunction(): var[0] = 22 # 修改列表的第一个元素 print('subfunction', var[0]) top.destroy() top = tk.Toplevel(root) top.title('top level') tk.Button(top, text='Button toplevel', command=subfunction).pack() root.wait_window(top) print('function', var[0]) # 这里会输出22 var = 0 root = tk.Tk() print(var) tk.Button(root, text='Button', command=function).pack() root.mainloop()
这两种方法都能满足你的需求:不用全局变量,也不用返回值,就能让function里的var变成subfunction里赋值的22。其中nonlocal更直观,适合Python 3+环境;列表包装法则兼容性更强。
备注:内容来源于stack exchange,提问作者user28976168




