一、函数预备知识
这里介绍函数形参、实参中可变位置参数和可变关键字参数;这部分知识会在之后参看requests库和自动化函数封装中使用
1.函数形参
python函数定义中,有两种类型可变参数定义方式:*args和**kwargs。你可以将不定数量的参数传递给一个函数。不定的意思是:预先并不知道,函数调用者会传递多少个参数,所以在这个场景下使用这两个类型关键字。其实并非必须写成*args和**kwargs。*才是必须的,你也可以写成*ar和**K。而写成*args和**kwargs只是一个通俗的命名约定。
python函数传递参数的方式有两种: 位置参数(positional argument)、关键字参数(keyword argument)
*args与**kwargs作为形参的区别,两者都是python中的可变参数:
*args表示任意多个无名参数(位置参数),它本质是tuple
**kwargs表示任意个关键字参数,它本质是dict
注意:* 与 ** 区别,在对实参进行操作时,* 有解包功能,** 只能操作dict类型。在下文实参部分将介绍
1.1 * 参数
函数接收任意长度的非关键字参数,系统将这些参数用tuple元组组合起来表示:
def location_parameter(*args): print(args) print( type(args) ) # 拆包 a,b,c = args print(b) location_parameter('a', 'b', 'c') # ('a', 'b', 'c') <class 'tuple'> 'b' location_parameter(1,2,3) # (1, 2, 3) <class 'tuple'> 2
1.2 ** 参数
函数接收任意长度的关键字参数,系统将这些参数用dict字典组合起来表示:
def keyword_parameter(**kwargs): print(kwargs) print( type(kwargs) ) keyword_parameter( p1 = 123, p2 = 'qwe', p3 = {'k':'v'} ) # {'p1': 123, 'p2': 'qwe', 'p3': {'k': 'v'}} <class 'dict'>
1.3 * 参数 和 ** 参数 联合使用
关键字参数必须在位置参数后面,否则会报错:
def test(*args, **kwargs): print(args, type(args1)) print(kwargs, type(kwargs)) test(a=1, b=2, 1, 2, 3) # SyntaxError: positional argument follows keyword argument
2. 函数实参
调用函数时,也可以使用 * 和 ** 符号;但 ** 只作用于 dict 类型实参。* 符号因具有拆包功能,可先作用 list, str, tuple, dict 类型实参;然后再参数传递。后面文章会python对打包、拆包知识进行介绍
2.1 * 参数
实参中的 * 后面跟的是可迭代对象,先拆包再传参,此时形参为位置参数或可变参数都可以:
def test1(a, b, c, d): print(a, b, c, d) test1(*['g', 2, 3, 4]) # g 2 3 4 def test2(*args): print(args, type(args)) test2(*['h', 2, 3, 4]) # ('h', 2, 3, 4) <class 'tuple'>
除了 list, str, tuple 等实参,还可以用 dict 作为实参,获取的是 dict 中的 key 值:
def test(a, b, c, d): print(a, b, c, d) test(*{'a': 1, 'b': 2, 'c': 3, 'd': 4}) # a b c d def test(*args): print(args, type(args)) test(*{'a': 1, 'b': 2, 'c': 3, 'd': 4}) # ('a', 'b', 'c', 'd') <class 'tuple'>
2.2 ** 参数
实参中的 ** 后面跟的是可迭代映射,获取的是可迭代映射的 value。( 对 dict 类型实参使用 ** 相当于将 { 'k' : v } 转化成 k = v 再传参 ) ;注意 ** 只作用 dict 实参
此时,当形参为位置参数时,获取的是可迭代对应key映射的value,当形参为关键字参数时,获取的是dict。
def test(a, b, c, d): print(a, b, c, d) test(**{'a': 1, 'b': 2, 'c': 3, 'd': 4}) # 1 2 3 4 test(**{'h': 1, 'b': 2, 'c': 3, 'd': 4}) # TypeError: test() got an unexpected keyword argument 'h' def test(**args): print(args, type(args)) test(**{'a': 1, 'b': 2, 'c': 3, 'd': 4}) # {'a': 1, 'b': 2, 'c': 3, 'd': 4} <class 'dict'>
总结,在查看requests库源码时,常见 * 和 ** 实参、形参;请大家掌握。
参考文章: