每日10行代码116: 编写高质量python代码的方法19:用关键字参数来表达可选的行为

与其他编程语言一样,调用python函数时,可以按位置传递参数。

def remainder(number, divisor):
    return number % divisor

assert remainder(20,7) ==6 

python中所有的位置参数,都可以按关键字传递。关键字参数的顺序不限,但位置参数必须在关键字参数之前。

remainder(20,divisor = 7)
remainder(number =20,divisor=7)
remainder(divisor=7,number=20)

上面这些调用都是等效的。但是下面这个会报错:

remainder(divisor=7,20)
>>>
SyntaxError: positional argument follows keyword argument

另外要注意的是每个参数只能指定一次。

remainder(20,number = 7)
>>>
TypeError: remainder() got multiple values for argument 'number'

灵活使用关键字参数,能带来三个重要的好处。
首先,以关键字参数来调用函数,能使读到这行代码的人更容易理解其含义。如果读到了remainder(20,7)这样的调用代码,那么必须 查看方法的实现代码,才能够明白这两个参数里面,究竟哪一个是被除数,哪一个是除数。若是改用关键字的形式来调用 ,则立刻就能根据number=20和divisor=7等写法来获知每个参数的含义。
关键字参数的第二个好处是,它可以在函数定义中提供默认值。在大部分情况下,函数调用者只需使用这些默认值就够了,若要开启某些附加功能,则可以指定相应的关键字参数。这样可以消除重复代码,并使代码变得整洁。
例如,要计算液体流入容器的速率。如果容器比较大,那么可以根据两个时间点上的重量差及时间差来判断流率。

def flow_rate(weight_diff, time_diff):
    return weight_diff/time_diff

weight_diff = 0.5
time_diff = 3
flow = flow_rate(weight_diff, time_diff)
print('%.3f kg per second'%flow)
>>>
0.167 kg per second

通常情况下,求出每秒中流过的千克数就可以了。然而某些时候,可能想根据传感器上一次的读数,在更大的时间跨度上面估算流率,如以小时或天来估算。只需给函数添加一个参数,用来表示两种时间段的比例因子 ,即可提供这种行为。

def flow_rate(weight_diff, time_diff, period):
    return (weight_diff/time_diff) *period

这样写的缺点是,每次调用函数时,都要指定period参数,即便我们想计算最常见的每秒流率,也依然要把1传给period参数。

flow_per_second = flow_rate(weight_diff, time_diff, 1)

为了使函数调用语句可能写得简单一些,我们可以给period参数定义默认值。

def flow_rate(weight_diff, time_diff, period=1):
    return (weight_diff/time_diff) *period

现在的period 参数,就成了可选参数。

flow_per_second = flow_rate(weight_diff, time_diff)
flow_per_hour = flow_rate(weight_diff, time_diff, period=3600)

这种办法适用于比较简单的默认值。如果默认值比较复杂,这样写就不太好了,那种情况可以参考本书第20条。
使用关键字参数的第三个好处,是可以提供一种扩充函数参数的有效方式,使得扩充之后的函数依然能与原有的那些调用代码相兼容。我们不需要迁移大量代码,即可给函数添加新的功能,这减少了引入bug的概率。
例如,要扩充上述的flow_rate函数,使它能够根据千克之外的其他重量单位来计算流率。为此我们添加一个可选的参数,用以表示千克与那种重量单位之间的换算关系。

def flow_rate(weight_diff, time_diff, period=1, units_per_kg=1):
    return ((weight_diff * units_per_kg) / time_diff) * period

units_per_kg参数的默认值是1,也就是说,如果该参数取默认值,那么 flow_rate 函数仍会以千克为重量单位来进行计算。这可以保证原来编写的那些函数调用代码,其行为都保持不变。而现在调用flow_rate的人,则可以通过这个新的关键字参数来使用该函数的新功能。

pounds_per_hour = flow_rate(weight_diff, time_diff, period=3600, units_per_kg=2.2)

这种写法只有一个缺陷,那就是period和units_per_kg 这种可选的关键字参数,仍然可以通过位置参数的形式来指定。

pounds_per_hour = flow_rate(weight_diff, time_diff, 3600, 2.2)

以位置参数的形式来指定可选参数,是容易令人困惑的,因为3600和2.2这样的值,其含义不清晰。最好的办法,是一直以关键字的形式来指定这些参数,而决不采用位置参数来指定它们。

要点:

  1. 函数参数可以按位置或关键字来指定。
  2. 只使用位置参数来调用函数,可能会导致这些参数值的含义不够明确,而关键字参数则能够阐明每个参数的意图。
  3. 给函数添加新的行为时,可以使用带默认值的关键字参数,以便与原有的函数调用代码保持兼容。
  4. 可行的关键字参数,总是应该以关键字形式来指定,而不应该以位置参数的形式来指定。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值