1.函数的进阶
-
*的魔性用法
# *的魔性用法: (函数中) def func(*args,**kwargs): print(args) # (1, 2, 3,'太白', 'wusir', '景女神') print(kwargs) l1 = [1, 2, 3] l2 = ['太白', 'wusir', '景女神'] func(l1,l2) func(*l1,*l2) # 当函数的执行时:*iterable 代表打散。 func(*[1, 2, 3],*(11,22),*'fdsakl') # 当函数的执行时:*iterable 代表打散。 def func(*args,**kwargs): print(args) print(kwargs) func(**{'name':"alex"},**{'age': 73,'hobby': '吹'}) 当函数的执行时:**dict 代表打散。 # 函数外:处理剩余元素 a,b,*c = [1,2,3,4,5] # a = 1 , b = 2 , c = [3, 4, 5] a,*c,b, = [1,2,3,4,5] # a = 1 , b = 5 , c = [3, 4, 5] a,*c = range(5) # a = 0 , c = [1, 2, 3, 4] a,*c,b = (1,2,3,4,5,6) # a = 1 , b = 6 , c = [2, 3, 4, 5] print(a,c,b)
-
形参角度的最终顺序
# *args的位置 # *args不能放在位置参数前面,a,b取不到值 def func(*args,a,b,sex='man',): print(a) print(b) print(sex) print(args) # print(kwargs) func(1,2,4,5,6) # args如果想要接收到值之前,肯定要改变sex默认参数。 def func(a,b,sex='man',*args): print(a) print(b) print(sex) print(args) # print(kwargs) func(1,2,4,5,6) def func(a,b,*args,sex='man'): print(a) print(b) print(sex) print(args) # print(kwargs) func(1,2,4,5,6) func(1,2,4,5,6,sex='women') # **kwargs # 位置参数,*args,默认参数,**kwargs def func(a,b,*args,sex='man',**kwargs,): print(a) print(b) print(sex) print(args) print(kwargs) func(1,2,4,5,6,name='太白',age=18)
-
从空间角度研究函数
全局名称空间: py文件运行时开辟的,存放的是执行的py文件(除去函数内部)的所有的变量与值(地址)的对应关系,整个py文件结束之后,才会消失。
临时(局部)名称空间: 函数执行时,在内存中临时开辟的一个空间,存放的函数中的变量与值的对应关系,随着函数的结束而消失。
内置名称空间:input,print,内置函数等。
-
取值顺序加载顺序
加载顺序:上面这三个空间,谁先加载到内存。
内置名称空间 ----》 全局名称空间 ----》 (函数执行时)临时名称空间
取值顺序:(就近原则)
-
作用域
全局作用域:全局名称空间,内置名称空间。
局部作用域:局部名称空间。
-
内置函数:globals,locals
"""此文件研究的是内置函数 globals locals""" name = 'alex' l1 = [1, 2, 3] def func(): age = '18' print(globals()) # 全局作用域所有的内容 print(locals()) # 当前位置 name = 'alex' l1 = [1, 2, 3] def func(): age = '18' oldboy = '老男孩教育' print(globals()) # 全局作用域所有的内容 print(locals()) # 当前位置的变量与值的对应关系 func() name = 'alex' l1 = [1, 2, 3] def func(): age = '18' oldboy = '老男孩教育' def inner(): name_class = 'python23期' print(globals()) # 全局作用域所有的内容 print(locals()) # 当前位置的变量与值的对应关系 inner() func()
-
高阶函数(嵌套函数)
# 例1: def func1(): print('in func1') print(3) def func2(): print('in func2') print(4) func1() print(1) func2() print(2) '''结果 in func1 3 1 in func2' 4 2 ''' # 例2: def func1(): print('in func1') print(3) def func2(): print('in func2') func1() print(4) print(1) func2() print(2) '''结果 1 in func2 in func1 3 4 2 ''' # 例3: def fun2(): print(2) def func3(): print(6) print(4) func3() print(8) print(3) fun2() print(5) '''结果 3 2 4 6 8 5 '''
-
关键字:global,nonlocal
在函数内部无法修改全局变量 count = 0 def func(): count += 1 func() # 报错: UnboundLocalError: local variable 'count' referenced before assignment # 解释器认为:如果你在局部作用域对一个变量进行修改了, # 你在局部作用域已经定义好这个变量了。 global 1. 可以在局部作用域声明一个全局变量。 # global 可以在函数内部创建一个全局变量 def func(): global name name = 1 print(globals()) name += 1 print(globals()) func() print(name) print(globals()) # 通过globals 可以查看到局部名称空间没有name变量,而是在全面名称空间内 2. 可以修改全局变量。 # global 可以在函数内部修改全局变量 count = 0 def func(): global count count += 1 print(count) func() print(count) # 通过运行函数,可以看出函数对全局变量count及逆行了修改 nonlocal 1. 不能操作全局变量。 2. 可以对父级作用域的变量进行修改,并且在当前作用域创建(复制)一份此变量。 # nonlocal 可以在子级函数内部调用父级函数的变量,并且在自己的空间内也复制了一个同样的变量,并且可以进行修改 def func(): count = 0 def inner(): nonlocal count count += 1 print(count) print(locals()) inner() print(locals()) func() # 通过locals 产看局部名称空间内变量,发酰两个函数空间内都存在count变量,并且都被修改
-
默认参数的坑
# 当你的默认参数是不可变数据类型时,可以直接在传参时进行修改 def func(a,b=False): print(a) print(b) func(1,True) # 当你的默认参数如果是可变的数据类型,你要小心了。 def func(a,l=[]): l.append(a) return l print(func(1)) # [1,] print(func(2)) # [1,2,] print(func(3)) # [1,2,3,] # 当你这样传入参数时,原参数不是直接被替代,而是一直往列表里添加
2.函数名的应用
-
函数名是一个特殊的变量。
def func(): print(666) print(func) # func的指向地址 <function func at 0x00000000003F1EA0> # func 与变量一样,指向的是一个内存地址 # 1,函数名指向的是函数的内存地址,加上()就执行这个函数。 # func() 这样才是执行函数的意思
-
函数名是一个变量。
print(age3) def func(): print(666) f1 = func f2 = f1 f2() f1() # 函数名与变量命一样,可以直接进行赋值
-
函数名可以作为容器类类型的元素。
def func1(): print('in func1') def func2(): print('in func2') def func3(): print('in func3') l = [func1, func2, func3] for i in l: i() # 函数名可以放在列表等容器里充当元素,可以for循环执行函数
-
函数名可以作为函数的实参。
def func1(): print('in func1') def func2(argv): argv() print('in func2') func2(func1) # 函数名也可以作为实参来进行传参
-
函数名可以作为函数的返回值
def func1(): print('in func1') def func2(argv): print('in func2') return argv ret = func2(func1) ret() # 函数名可以作为函数的返回值