很多时候,我们编写的代码出现莫名的错误,代码量多的情况下,排查非常困难。这主要是我们对命名空间、作用域的理解不够导致的。本文就用几个案例来直观展示下这类问题。
P 1、命名空间
什么是命名空间,有什么作用?
官方文件说:“namespace (命名空间)是从名称到对象的映射。一个命名空间的作用域是 Python 代码中的一段文本区域,从这个区域可直接访问该命名空间。”
白话就是无论一个.py文件、一个函数、一个类,或者一个文件夹,它自身就是一个命名空间,可以向下映射,互相隔离、无冲突。比如:files.py文件中的一个函数myfunc、一个变量myvar、一个类mycls等,都必须是唯一的名称。此时,函数、类可以再向下映射出各自的变量func_var、方法cls_func等,这些也都有自己的名字。这些名字要求,在任何的同级都不能出现重复,保证各个名称的隔离、唯一性,从而避免出现名称冲突。
如下的命名不会产生任何冲突:
files.myfunc.func_varfiles.myvarfiles.myclsfiles.mycls.cls_func
官方文件说:“一个命名空间的作用域是 Python 代码中的一段文本区域,从这个区域可直接访问该命名空间。”
先理解官方的解释:命名空间是在不同时刻创建的,且拥有不同的生命周期。内置名称的命名空间是在 Python 解释器启动时创建的,永远不会被删除。模块的全局命名空间在读取模块定义时创建;通常,模块的命名空间也会持续到解释器退出。函数的局部命名空间在函数被调用时被创建,并在函数返回或抛出未在函数内被处理的异常时,被删除。
P 2、作用域
什么是局部变量、全局变量、nonlocal变量?
上述这些,讲的都是变量或者命名空间在命名空间中的作用域。通过global、nonlocal关键字可以改变变量作用域,它们分别表示全局变量、外层变量。其中,global声明的变量是在外层所有命名空间中的某个地方定义的。而nonlocal声明的变量只是在外1层命名空间的某个地方定义。
(1)局部变量
num = 10def myfunc(): num = 20 print(f'myfunc.{num=}')myfunc()print(f'global.{num=}')
输出:
myfunc.num=20global.num=10
可以看到,函数内外部变量名称是一致的,但互不影响,各自发挥作用。
# 全局变量(两层空间)num = 10def myfunc(): global num num = 20 print(f'myfunc.{num=}')myfunc()print(f'global.{num=}')
myfunc.num=20global.num=20
可以看到,由于global关键字的影响,两层命名空间下,函数内可以修改全局声明变量。
# 全局变量(三层空间)num = 10def outer(): def myfunc(): global num num = 20 print(f'myfunc.{num=}') myfunc()outer()print(f'global.{num=}')
myfunc.num=20global.num=20
可以看到,由于global关键字的影响,三层命名空间下,函数内可以修改全局声明变量。更多层也是一样的。
(3)nonlocal变量
# 非本地变量(三层空间)num = 10def outer(): def myfunc(): nonlocal num num = 20 print(f'myfunc.{num=}') myfunc()
Cell In[14], line 5 nonlocal num ^SyntaxError: nobinding for nonlocal 'num' found
直接定义出错,指示外层空间未定义num变量。修改下代码,在outer()函数空间定义num变量。
# 非本地变量(三层空间)num = 10def outer(): num = 15 def myfunc(): nonlocal num num = 20 print(f'myfunc.{num=}') myfunc() print(f'outer.{num=}')outer()print(f'global.{num=}')
myfunc.num=20outer.num=20global.num=10
可以看到,每层空间都有num定义,但最内层函数myfunc()中,声明了nonlocal变量num,并修改为20,导致了外层函数outer()中定义的num发生了变化,同样输出了20。但全局定义的变量num值始终为10,保持不变。
-------------------------它是数字世界里的一把杀猪刀
却总能巧夺天工
它的世界是纯粹0、1组合
却总能创造无尽幻想
......
本公众号关注数据价值分析、编程学习,将不定期更新社会热点数据分析结果、编程技巧,分享数据分析工具、方法、学习等内容,欢迎有兴趣的小伙伴加入。