函数为了拓展,对于那些传入的实参数量不固定,万能参数,动态参数,通常使用*args,**kwargs表示。
1 def sum1(*args): 2 print(args) 3 sum1(1,2,3,4) # (1, 2, 3, 4)
在函数的定义时,*args表示位置参数,作为聚合用。
*args将所有的实参的位置参数聚合到一个元组,并将这个元组赋值给args
1 def sum1(*args, **kwargs): 2 print(args) # (1, 2, 3, 4, 5) 3 print(kwargs) 4 sum1(1,2,3,4,5, name = 'colin', age = '27') # {'name': 'colin', 'age': '27'}
该方式下,还有拆分功能,如下列例题:将l1与l2拆分一一打印出来:
一般方法如下:
1 def func1(*args): 2 l = [] 3 for i in args: 4 if type(i) is list: 5 for j in i: 6 l.append(j) 7 else: 8 l.append(i) 9 return l 10 l1 = [1,2,3] 11 l2 = [111,222,'alex'] 12 print(func1(l1,l2))
稍微简单的方法如下:
1 def func1(*args): 2 return args[0] + args[1] 3 l1 = [1,2,3] 4 l2 = [111,222,'alex'] 5 print(func1(l1,l2))
用本文介绍的方法如下:
1 def func1(*args): 2 print(args) 3 l1 = [1,2,3] 4 l2 = [111,222,'alex'] 5 func1(*l1,*l2) # (1, 2, 3, 111, 222, 'alex')
此外,对于加了两个星号 ** 的参数会以字典的形式导入。
1 def func1(*args, **kwargs): 2 print(kwargs) 3 func1(**{'name':'colin'},**{'age' : 27}) # {'name': 'colin', 'age': 27}
接下来讨论形参的顺序,比较位置参数,默认参数,*args,**kwargs的先后
位置参数,默认参数
1 def func(a, b, sex = '男'): 2 print(a) # 100 3 print(sex) # 男 4 func(100,200) 5 def func(a, sex = '男',b): 6 print(a) 7 print(sex) 8 func(100,200) # 报错
位置参数在前,默认参数在后,否则报错,是因为200的值赋值给默认参数sex,而b没有参数传入,所以报错
位置参数,*args,默认参数
1 def func(a,b,sex = '男',*args): 2 print(a,b) # 100 200 3 print(sex) # 1 4 print(args) # (2, 3, 4, 5) 5 func(100,200,1,2,3,4,5)
1 def func(a,b,*args,sex = '男'): 2 print(a,b) # 100 200 3 print(sex) # 男 4 print(args) # (1, 2, 3, 4, 5) 5 func(100,200,1,2,3,4,5)
从上面可以分析,若默认参数在前的化,实参1会将默认参数sex覆盖,后面的参数都给*args,
性别赋值除了问题,而默认参数放在最后则消除了这个影响,因此顺序为:位置参数,*args,默认参数
位置参数,*args,**kwargs,默认参数
1 def func(a,b,*args,**kwargs,sex ='男'): 2 print(a,b) 3 print(sex) 4 print(args) 5 func(100,200,1,2,3,4,5,sex ='女')
1 def func(a,b,*args,sex ='男',**kwargs): 2 print(a,b) # 100,200 3 print(sex) # 女 4 print(args) # (1, 2, 3, 4, 5) 5 print(kwargs) # {} 6 func(100,200,1,2,3,4,5,sex ='女')
从上面分析可知,当默认参数放在最后时,会报错,这是因为不固定参数**kwargs将sex参数包括进去,
导致默认参数没有参数与它对应,导致报错。
综上:参数顺序为:位置参数,*args,默认参数,**kwargs
命名空间
在python中,名称空间可以分为三种:
1 全局名称空间
2 局部名称空间(临时):在函数的运行中开辟的临时的空间叫局部命名空间
3 内置名称空间
作用域分类
全局作用域 全局名称空间
内置名称空间
局部作用域 局部名称空间(临时)
其取值顺序为:
局部名称空间 > 全局名称空间 > 内置名称空间 单向从小到大范围
1 len = 6 2 def func1(): 3 len = 3 4 func1() 5 print(len) # 6
1 count = 1 2 def func1(): 3 count = count + 1 # local variable 'count' referenced before assignment 4 print(count) 5 func1()
如果你在局部名称空间,对一个变量进行修改,那么解释器会认为你的这个变量在局部中已经定义了,
但是对于上面的例题,局部中没有定义,所以他会报错。
解决方法1
1 count = 1 2 def func1(): 3 count = 3 4 count = count + 1 # 4 5 print(count) 6 func1()
解决方法2: 在局部名称空间可以对全局变量进行修改
1 count = 1 2 def func1(): 3 global count 4 count = count + 1 # 2 5 print(count) 6 func1()
nonlocal
子函数对父函数的变量进行修改
此变量不能是全局变量
1 def func1(): 2 count = 666 3 def func2(): 4 nonlocal count 5 count += 1 6 print(count) # 667 7 func2() 8 func1()