◎知识点
函数的定义之使用*定义个数可变的位置形参
函数的调用之使用*将序列中的每个元素都转换为位置实参
函数的定义之使用**定义个数可变的关键字形参
函数的调用之使用**将字典中的每个键值对转换为关键字实参
函数的各种参数大总结
◎脚本练习
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ @FileName: function_arguments3.py @Function: python function arguments @Author: Zhihe An @Site: https://chegva.com @Time: 2021/7/4 """ """一、函数的定义之使用*定义个数可变的位置形参""" """ 定义函数时,可能无法事先确定传递的位置实参的个数,在这种情况下,可以在形参前添加一个*, 将形参定义为个数可变的位置形参,从而可以接收0个或任意多个位置实参。这些位置实参会将个数可变的 位置形参初始化为一个元组 """ def f(*args): print(args) f() # () f(1) # (1,) f(1, 2, 3) # (1, 2, 3) """ 定义函数时,最多只能定义一个个数可变的位置形参 """ # def fun(*arg1, *arg2): # multiple * parameters are not allowed # print(arg1, arg2) """ 很多内置函数都定义了个数可变的位置形参。例如,内置函数print()的定义为: def print(self, *args, sep=' ', end='\n', file=None): """ print() # print(1) # 1 print(1, 2) # 1 2 print(1, 2, 3) # 1 2 3 """ 通常,把个数可变的位置形参定义为最后一个形参,以便接收所有剩余的位置实参 """ def fun1(a, b, *c): print('a =', a, 'b =', b, 'c =', c) fun1(1, 2, 3, 4, 5) # a = 1 b = 2 c = (3, 4, 5) """ 如果个数可变的位置形参不是最后一个形参,那么其后面的所有形参都被定义为只能接收关键字实参的 关键字形参。如果向这些关键字形参传递位置实参,所有的位置实参都会被算作个数可变的,从而导致 关键字实参的缺失 """ def fun2(a, *b, c, d): print('a =', a, 'b =', b, 'c =', c, 'd =', d) fun2(1, 2, 3, 4, c = 5, d = 6) # a = 1 b = (2, 3, 4) c = 5 d = 6 # 可能你想把实参5和6分别传递给形参c和d, # 但是2、3、4、5、6全被算作了个数可变的位置实参,从而导致形参c和d对应实参的缺失 # fun2() missing 2 required keyword-only arguments: 'c' and 'd' # fun2(1, 2, 3, 4, 5, 6) """二、函数的调用之使用*将序列中的每个元素都转换为位置实参""" def f(a, b, c): print('a =', a, 'b =', b, 'c =', c) f(1, 2, 3) # a = 1 b = 2 c = 3 L = [1, 2, 3] # 列表L整体作为一个位置实参 # f(L) # f() missing 2 required positional arguments: 'b' and 'c' f(L[0], L[1], L[2]) # a = 1 b = 2 c = 3 """ 调用函数时,可以在序列前面添加一个*,从而将序列中的每个元素都转换为一个单独的位置实参 """ # 相当于:f(L[0], L[1], L[2]): f(*L) # a = 1 b = 2 c = 3 """ 注意和个数可变的位置形参进行区分。个数可变的位置形参是在定义函数时使用,使用*将序列中的 每个元素都转换为位置实参是在调用函数时使用 """ def fun(*args): print(args) # 列表L整体作为一个位置实参 fun(L) # ([1, 2, 3],) # 先将序列中的每个元素都转换为一个单独的位置实参 # 再用这些位置实参将个数可变的位置形参初始化为一个元组 fun(*L) # (1, 2, 3) """三、函数的定义之使用**定义个数可变的关键字形参""" """ 定义函数时,可能无法事先确定传递的关键字实参的个数,在这种情况下,可以在形参前添加两个*, 将形参定义为个数可变的关键字形参,从而可以接收0个或任意多个关键字实参。这些关键字实参会将 个数可变的关键字形参初始化为一个字典 """ def f(**kwargs): print(kwargs) f() # {} f(a = 1) # {'a': 1} f(a = 1, b = 2, c =3) # {'a': 1, 'b': 2, 'c': 3} """ 定义函数时,最多只能定义一个个数可变的关键字形参 """ # def fun(**kwargs1, **kwargs2): # multiple ** parameters are not allowed # print(kwargs1, kwargs2) """ 很多内置函数都定义了个数可变的关键字形参。例如,内置函数sorted()的定义为: def sorted(*args, **kwargs): """ L = ['Python', 'Java', 'Swift'] print(sorted(L)) # ['Java', 'Python', 'Swift'] print(sorted(L, key = len)) # ['Java', 'Swift', 'Python'] print(sorted(L, key = len, reverse = True)) # ['Python', 'Swift', 'Java'] """ 因为调用函数时位置实参必须位于关键字实参之前,所以个数可变的位置形参必须位于 个数可变的关键字形参之前 """ # def fun(**kwargs, *args): # * parameter after ** parameter # print(kwargs, args) def fun(*args, **kwargs): print(kwargs, args) """四、函数的调用之使用**将字典中的每个键值对转换为关键字实参""" def f(a, b, c): print('a =', a, 'b =', b, 'c =', c) f(a = 1, b = 2, c = 3) # a = 1 b = 2 c = 3 d = {'a': 1, 'b': 2, 'c': 3} # 字典d整体作为一个位置实参 # f(d) # f() missing 2 required positional arguments: 'b' and 'c' f(a = d['a'], b = d['b'], c = d['c']) # a = 1 b = 2 c = 3 """ 调用函数时,可以在字典前添加两个**,从而将字典中的每个键值对都转换为一个单独的关键字实参 """ # 相当于:f(a = d['a'], b = d['b'], c = d['c']) f(**d) # a = 1 b = 2 c = 3 """ 注意和个数可变的关键字形参进行区分。个数可变的关键字形参是在定义函数时使用, 使用**将字典中的每个键值对都转换为关键字实参是在调用函数时使用 """ def fun(**kwargs): print(kwargs) # 先将字典中的每个键值对都转换为一个单独的关键字实参 # 再用这些关键字实参将个数可变的关键字形参初始化为一个字典 fun(**d) # {'a': 1, 'b': 2, 'c': 3} """五、函数的各种参数大总结""" def f1(a, b = 5, *args, **kwargs): print('a =', a, 'b =', b, 'args =', args, 'kwargs =', kwargs) f1(2, 6, 7, 8, c = 9) # a = 2 b = 6 args = (7, 8) kwargs = {'c': 9} f1(2) # a = 2 b = 5 args = () kwargs = {} def f2(a, b = 5, *, c, **kwargs): print('a =', a, 'b =', b, 'c =', c, 'kwargs =', kwargs) f2(*(3, 6), **{'c': 8, 'd': 10}) # a = 3 b = 6 c = 8 kwargs = {'d': 10} f2(3, c = 8, d = 10) # a = 3 b = 5 c = 8 kwargs = {'d': 10}
▽ 个数可变的位置形参后面的形参
▽ 函数参数综合实例1
▽ 函数参数综合实例2
▽ 函数各种参数总结表格