函数进阶

名称空间与作用域

名称空间

名称空间分为全局名称空间、局部名称空间和内置名称空间

全局名称空间:存放的是py文件中变量与值的对应关系

局部名称空间:存放的是函数体里面的变量与值的对应关系

内置名称空间:存放内置函数,关键字等

作用域

全局作用域:内置名称空间、全局名称空间

局部作用域:局部名称空间

python代码执行过程中是怎样存储对象的呢

对于变量

1. 遇到初始化对象命令,创建名称空间,保存变量与值的对应关系

2. 存放的是变量名和值的内存地址

对于函数

1. 遇到函数定义,只是在名称空间里存放函数名,此时对于函数内部的变量是不关心的

2. 遇到函数执行,创建临时名称空间(局部名称空间),临时名称空间随着函数的结束而消失

加载顺序与取值顺序

加载顺序:就是加载在内存中的顺序

1. 内置名称空间

2. 全局名称空间

3. 局部名称空间

取值顺序

1. 局部名称空间

2. 全局名称空间

3. 内置名称空间

取值顺序也称为LEGB规则

L:Local         局部名称空间

E: Enclosed    父级名称空间

G: Global        全局名称空间

B: Built-in        内置名称空间

globals()与locals()

globals()和locals()是内置函数,其功能如下:

globas(): 返回一个字典,包括全局作用域的内容

locals(): 返回一个字典,包括当前作用域的内容

实例1:

1 def func():
2     name = "barry"
3     age = 18
4     print(globals())
5     print(locals())   
6 
7 
8 func()

执行结果

{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000027DED6DA400>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/名称空间与加载顺序.py', '__cached__': None, 'func': <function func at 0x0000027DED7A9B70>}
{'age': 18, 'name': 'barry'}

实例2:

 

动态参数*args与**kwargs

*args和**kwargs可以接收任意数量的参数,args接收位置参数,kwargs接收关键字参数

1 def func(*args, **kwargs):    # 在函数的定义时,*, **代表聚合
2     print(args)
3     print(kwargs)
4 
5 
6 func(*[1, 2, 3], *"abc", **{"name": "Robin", "age": 18}, gender="female")    # 函数的执行时,*, **代表打散

执行结果

(1, 2, 3, 'a', 'b', 'c')
{'name': 'Robin', 'age': 18, 'gender': 'female'}

在函数的定义时,*和**表示聚合,*将位置参数聚合成元组,**将关键字参数聚合成字典;在函数执行时,*和**表示打散

在python3.6中,*的适用范围扩展到非函数领域

1 a, b, *args = [i for i in range(10)]
2 print(a, b, args)
3 
4 a, b, *args = (1, 2, 3, 4, 5, 6)   # *args会将多余的参数放到一个列表里(只会是列表)
5 print(a, b, args)

输出

0 1 [2, 3, 4, 5, 6, 7, 8, 9]
1 2 [3, 4, 5, 6]

 

global与nonlocal

global和nonlocal是两个关键字,注意不要与globals()和locals()弄混了

global

1. 声明一个局部变量

2. 在局部作用域内对全局变量进行操作

 1 name = "Bill"
 2 
 3 
 4 def func():
 5     global name
 6     name = "Alice"
 7 
 8 
 9 func()
10 print(name)

执行结果

Alice

nonlocal

正常来说局部作用域对全局作用域的变量只能引用而不能修改

1 count = 1
2 
3 
4 def func():
5     print(“count:", count)  # 可以打印
6 
7 
8 func()

执行结果

count: 1
1 count = 1
2 
3 
4 def func():
5     # print("count:", count)  # 可以打印
6     count += 1   # 报错
7 
8 
9 func()

执行结果

UnboundLocalError: local variable 'count' referenced before assignment

除了局部作用域不能修改全局作用域之外,内层函数也不能修改外层函数的变量,如果要修改那么要用到nonlocal

nonlocal作用

1. 在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改

2. 引用的哪层,从哪层以下此变量全部发生更改

 1 def wrapper():
 2     name = 'alex'
 3 
 4     def inner():
 5         nonlocal name
 6         name += 'b'
 7         print(name)
 8     print('1', name)
 9     inner()
10     print('2', name)
11 
12 
13 wrapper()

执行结果

1 alex
alexb
2 alexb

函数嵌套

这个没啥难的,只要记住两点

1. 遇到函数定义就跳过

2. 遇到函数调用就跳转到函数体执行

 

posted @ 2018-12-30 22:13  乘月归  阅读(175)  评论(0编辑  收藏  举报