0
点赞
收藏
分享

微信扫一扫

Effective Python 第25条:设计只能以关键字和只能按位置传入参数

书坊尚 2022-01-21 阅读 52
python后端

在python中函数传参可以使用位置传参和关键字传参组合。

现定义一个函数,计算两个数相除的结果,但是,会有两个参数判断,如果除数为0,是抛出ZeroDivisionError,还是返回无穷(infinity),如果结果溢出,是抛出OverflowError,还是返回0。

如下:

def safe_division(number, divisor, 
                  ignore_overflow, 
                  ignore_zero_division):
    try:
        return number / divisor
    except OverflowError:
        if ignore_overflow:
            return 0
        raise 
    except ZeroDivisionError:
        if ignore_zero_division:
            return float('inf')
        raise 

如果想在结果溢出返回0,可以如下调用:

res = safe_division(1.0, 100**500, True, True)
print(res)

如果想在除数为0返回无穷,如下调用:

res = safe_division(1.0, 0, False, True)
print(res)

但是可以看到函数最后两个参数都是boolean值,调用者很容易弄错位置。如果我们想调用者后面两个参数必须按照关键字传参,应该如何做?

在python3,8后,可以声明只能通过关键字指定的参数(key-only argument)。可以使用*号把参数分开,左边是位置参数,右边是关键字参数。如下:

def safe_division(number, divisor, *, # 前面是位置参数,后面是关键字参数
                  ignore_overflow=False,
                  ignore_zero_division=False):
    try:
        return number / divisor
    except OverflowError:
        if ignore_overflow:
            return 0
        raise
    except ZeroDivisionError:
        if ignore_zero_division:
            return float('inf')
        raise

这样如果后面两个还按位置传参,就会出错:

res = safe_division(1.0, 0, False, True)
# TypeError: safe_division() takes 2 positional arguments but 4 were given

当然,这时候后面两个关键字参数还是可以只传一个,另一个用默认值:

res = safe_division(1.0, 0, ignore_zero_division=True)

函数前面两个参数只是两个相除的数,名称意义并不大,如果想让调用者只能按位置传参,还如何做?

python3.8还提供了只能通过位置传参的参数(keywoed-only argument)。以 /分割,表示左边只能按位置传参。如下:

def safe_division(number, divisor, /, *,
                  ignore_overflow=False,
                  ignore_zero_division=False):
	pass

这时候,前面两个参数只能以位置传参,否则报错:

res = safe_division(number=1.0, divisor=0)
# TypeError: safe_division() got some positional-only arguments passed as keyword arguments: 'number, divisor'

如果是在两个符号之间的参数,则既可以用关键字传参,又可以位置传参。这里不在演示。

总结

python3.8之后,函数的参数列表可以使用*/分割,调用时,在*右边的必须使用关键字传参,在 / 左边的必须使用位置传参,两个之间的既可以关键字传参。也可以使用位置传参。

注意*要写在/之后。

举报

相关推荐

0 条评论