函数参数这块在前面的博客中没有展开,现在专门整理出来:
1、参数的数量:
1)没有参数:就是定义函数和调用函数的括号中都不写内容。
2)有一个参数:可以是任何数据类型。
3)有多个参数:例如位置参数。
2、位置参数:
概念:按照从左到右的顺序依次定义的参数,就称之为位置参数。
位置形参:在定义函数阶段,按照从左到右的顺序直接定义的“变量名”。必须被传值、多一个不行、少一个也不行。
位置实参:在函数调用阶段,按照从左到右的顺序依次传入的值。
例1:
def my_sum(a, b): # 位置形参
res = a + b
return res
ret = my_sum(1, 2) # 位置实参
print(ret)
3、关键字参数:
关键字实参:在函数调用阶段, 按照key=value的形式传入的值。就是指名道姓地给某个形参传值,可以完全不参照顺序。
例2:
def my_sum(a, b):
res = a + b
print('a: ', a)
print('b: ', b)
return res
ret = my_sum(b=1, a=2)
print(ret)
4、默认参数(默认形参): 在定义函数阶段,就已经被赋值的形参,称之为默认参数。在定义阶段,就被赋值,意味着在调用阶段就不用再为其赋值,也就是可以不传。
注意:所有位置参数必须出现在默认参数前,包括函数定义和调用。
例3:
def my_sum(a, b=7): # b是默认参数,有默认值7
res = a + b
print('a: ', a)
print('b: ', b)
return res
ret = my_sum(1) # 调用时,就不用再为b赋值了
print(ret)
5、位置形参和默认参数(默认形参)可以混合使用:
1、规则:位置形参必须位于默认形参的左边,但关键字参数之间是不存在先后顺序的。
例4:
def my_sum(a=7, b): # 现在我将默认参数放在位置参数的前面,我们看看有什么报错?
res = a + b
print('a: ', a)
print('b: ', b)
return res
ret = my_sum(1)
print(ret)
结果截图:
我们看到这个语法错误的意思:非默认参数跟在默认参数之后。也就是说位置参数是在默认参数之后了,更进一步说默认参数写在位置参数前面了。
6、默认参数的值是在函数定义阶段赋值的,准确地说被赋予的是值的内存地址。
例5:
a = 7
def func(x, y=a): # y 赋予的是7的内存地址
print(x, y)
a = 8
func(1)
结果:
例6:
a = [1, 3]
def func(x, y=a): # y 被赋予[1, 3]的内存地址
print(x, y)
a.append(9)
func(1)
结果:
7、默认值可以被指定为任意数据类型,但是最好不要使用可变类型,函数最理想的状态:函数的调用只跟函数本身有关系,不受外界代码的影响。
例7:
def func(x, y, z, l=None):
if l is None:
l = []
l.append(x)
l.append(y)
l.append(z)
print(l)
func(1, 2, 3)
func(11, 22, 33)
list_1 = [111, 222]
func(1, 2, 3, list_1)
8、可变参数:
定义函数的时候,我们不确定调用的时候会传递多少个参数(不传参也可以),此时,可用包裹packing位置参数或者包裹关键字参数,来进行参数传递,会显得非常方便。
8.1 包裹位置传递:
def my_sum(*args):
sum = 0
for i in args:
sum = sum + i
return sum
print(my_sum(1, 2))
print(my_sum(1, 2, 3))
print(my_sum(1, 2, 3, 4))
结果:
我们传递的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是包位置传递。
如果将def my_sum(*args) 换成 def my_sum(*a) ,也是可以的,使用a来代替args。
之所以叫args,这种一种习惯:
我们再看一个例子:
def func(*args): # 站在形参的角度上,给变量加上*,就是组合传来的值。
print(args)
func(1, 2, 3, 4, 5)
l = [1, 2, 3, 4, 5]
func(*l) #站在实参的角度上,给一个序列加上*, 就是将这个序列按照顺序打散。
注意:两个星号的作用,有“组合”和“打散”的作用。
8.2 包裹关键字传递:
def func(**kwargs):
print(kwargs)
print(func(a=1))
print(func(a=1, b=2, c=3))
kargs是一个字典(dict),搜集所有关键字参数。
那么可以将两者结合起来:
def func(*args, **kwargs):
print(args, kwargs)
print(func(1, 2, 3, 4 = 'good', 5 = 'best')
我们再看一个例子:
def func(**kwargs):
print(kwargs)
func(a=1, b=2)
d = {'a': 1, 'b': 2}
print(func(**d))
看看这个两个星号**的作用。也是“组合”和“打散”的作用。
9、解包裹参数:
*args和**kwargs, 也可以在函数调用的时候使用,称之为解包(unpacking)。
9.1 在传递元组的时候,让元组的每一个元素对应一个位置参数:
def print_hello(name, sex):
print(name, sex)
args = ('tanggu', '男')
print_hello(*args)
2、在传递字典的时候,让字典的每个键值对作为一个关键字参数传递给函数。
def print_hello(**kwargs):
print(kargs)
kargs = {'name': 'tanggu', 'sex': u'男'}
print_hello(**kwargs)
10、位置参数、默认参数和可变参数的混合使用:
10.1 规则:先位置参数、*args, 默认参数、**kwargs。
11、函数的注释:
11.1 可以给代码加行注释;
11.2 使用三引号,里面写函数的功能、参数说明和返回值说明。我们看下一个函数的注释:
这是一个非常标准的函数注释。