名称空间与作用域
-
当你定义一个num = 123时,123存放在内存中,那num变量名存放在哪里呢?答案就是名称空间,名称空间就是用来存放名字的地方。
-
名称空间分类:
-
内置名称空间
-
-
全局名称空间
-
执行py脚本的时候加载全部名称空间
-
-
局部名称空间
-
执行到函数的时候加载函数内部的名称空间,成为局部名称空间
-
-
-
函数的查找方式
-
当执行一个函数的时候,首先会在当前所在的名称空间查找,如果找不到会继续向外找
>>> def max(): ... print('from max') ... >>> def func(): ... def max(): ... print('from func.max') ... max() ... >>> func() # 执行func的时候首先在函数体内部寻找,如果有则打印内部的 from func.max >>> max() # 这调用max会执行什么呢?肯定是 from max,因为查找顺序一定是从当前名称空间查找,如果全局没有则会去查找内置的,而不会去查找局部的了 >>> del max >>> max # 查找内置名称空间的函数 <built-in function max> >>> def func(): # 函数体内部没有max,则从当前向外查找 ... max() ... >>> func() from max
-
-
函数嵌套
-
函数嵌套就是在函数体的内部定义函数,嵌套多层
>>> def func(): ... def func1(): ... def func2(): ... print('from func2') ... func2() ... func1() ... >>> func() from func2 >>> func1() Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'func1' is not defined # 调用func1() 为什么会报错呢?这就用到了作用域
作用域
-
作用域分为两种
-
全局作用域
-
全局名称空间
-
内置名称空间
-
-
局部作用域
-
局部名称空间
-
-
-
什么是作用域呢?
-
作用域用到了里、外的概念,我在里面操作的是我自己的不会操作外面的,而在外面操作的同理
>>> num = 123 >>> def func(): ... num = 456 ... print(num) ... >>> func() # 调用函数体内部的num 456 >>> num # 调用全局的num 123 # 无论在func函数体内怎么操作,都不会影响外部的num变量 >>> num = 11111111 # 修改的是全局的num >>> num 11111111 >>> func() # 不影响函数内部 456 # 如果理解了作用域的概念,来解读一下函数嵌套提到的问题,举个例子 >>> del num # 将全局的num变量删除 >>> num # 此时调用num变量,会输出456吗? 是不会的 Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'num' is not defined # 为什么调用不到呢?还记得之前我说过,在外面也就是全局操作是不会应用到函数体内部的 当前例子查找流程: 全部查找num找不到 --> 内置空间查找还是找不到 --> 报错 不会去函数内部去查找局部的了 总结: 一定要记住,查找顺序是从当前空间查找,找不到就会向外查找,而不会像内查找
-
-
global与nolocal关键字
-
如果一定要在函数内部修改局部的变量呢?这就用到了global关键字
>>> num = 123 >>> def func(): ... global num # 声明要修改的是全局的 ... num = 456 ... >>> func() 456 # 不推荐使用,这样会污染外部的变量,应该做到内外互不干扰
-
那么nolocal关键字是干嘛的呢?
-
修改函数体内部上层嵌套函数体定义的变量
>>> num = 123 >>> def func(): # 如果在这(最外部函数体)找不到就会报错,而不会去寻找全局 ... num = 456 ... def func1(): ... num = 789 # 本例,在这找到了,如果在这找不到则会去找func里面的num ... def func2(): ... nonlocal num # 声明修改上层变量 ... num = 111111 ... print(num) ... func2() ... print(num) ... func1() ... print(num) ... >>> func() 111111 111111 456 >>> num 123 总结: 从下向上一层一层函数体寻找,找到则修改不继续寻找,找不到则一直找,查找到最外层函数体还是没找到就会报错,不会去查找全局
-
-