python类函数重构 python构造函数重载( 二 )


func('rechar', age = 27)#name是按顺序匹配,age按名称匹配
在python中,当按照参数名称进行匹配参数是,参数传递的顺序是可以任意的,不要求按照函数定义中参数的顺序进行传递 。在使用名称匹配时,如果需要混合使用按顺序匹配规则,则按顺序匹配的参数必须出现在按key匹配的参数前,否则会报错:
func(name = 'rechar', 27)
以上调用会报如下错误:
三、函数定义中的”*name“
python在给按顺序匹配和按key匹配的参数赋完值后,如果发现调用者传入的参数仍有未匹配上的会发生什么情况呢?看一下下面的例子:
func('rechar', 27, 32)
运行时我们看到如下错误:
Traceback (most recent call last):
File "E:\tmp\tt.py", line 5, in module
func('rechar', 27, 32)
TypeError: func() takes 2 positional arguments but 3 were given
哦 , python会抱怨我们传递的参数太多了 。那如果确实在一些情况下 , 我们无法保证传递的参数数量一定和函数需要的参数数相等怎么办呢?这是就是*iterable这种参数该登场的时候了 , 假如在定义函数定义是,我们增加了一个参数,这个参数以一个”*“开始,那么这个参数实际上是一个tuple类型 。假如传递的参数比需要的多,那那些多余的参数会被放入这个tuple中 。例如,
def func(name, age, *other):
print(name, age, other)
那么,
func('rechar', 27, 32)
这个调用的输出如下:
rechar 27 (32,)
四、函数定义中的”**name“
python在将所有未匹配上的非按名称匹配的参数装入参数中的tuple之后,假如还有未匹配上的按名称匹配的参数那情况会怎样呢?首先来看一下下面的示例:
def func(name, age):
print(name, age)
func(name = 'rechar', age = 27, pay='1800')
执行时,python又抱怨了:
Traceback (most recent call last):
File "E:\tmp\tt.py", line 5, in module
func(name = 'rechar', age = 27, pay='1800')
TypeError: func() got an unexpected keyword argument 'pay'
它说func这个函数没有名称为”pay“的参数,这种情况或许出现在我们函数重构之后,原来函数时有这个参数的 。而这个函数调用可能在别处没有被修改 。假设即使给了”pay“这个参数 , 程序的正确性不受影响,没错,这就是”**name“参数的用武之地了 。
假如在函数定义中,给函数增加一个以”**“开头的参数,那么这个参数实际上是一个dict对象,它会将参数调用中所有没有被匹配的按名称传递的参数都放入这个dict中 。例如,
def func(name, age,**other):
print(name, age, other)
func(name = 'rechar', age = 27, pay='1800')
那么运行结果输出,
rechar 27 {'pay': '1800'}
看到了吧 , 这里的other就将没有匹配的”pay=‘1800’“收入囊中了 。
五、规定调用必须按名称匹配
当我们在定义函数时 , 如果第一个参数就是”*name“参数,那么可想而知,我们无法使用按顺序匹配的方式传递 , 因为所有的按顺序传递的参数值最终的归宿都会是这里的tuple当中 。而为了给后续的参数传递值,我们只能使用按名称匹配的方法 。
六、”**“参数只能出现在最后一个形参之后
想想为什么?其实很好理解,因为出现在”**“形参之后的形参,无论使用按顺序传递还是按名称传递,最终都无法到达参数值真正应该需要到的地方 。所以python规定,如果需要”**“参数,那它必须是最后一个形参 。否则python会报语法错误 。
七、函数调用中的”*“
在表格中我们看到了有func(*iteratable)的调用,这个调用的意思是,iteratable必须是一个可迭代的容器,比如list、tuple;作为参数传递值 , 它最终传递到函数时 , 不是以一个整体出现,而是将其中的元素按照顺序传递的方式,一次赋值给函数的形参 。例如,

推荐阅读