python:函数形参列表中的斜杠(/)是什么意思?
1 前言
函数参数列表中的斜杠表示在它之前的形参都是仅限位置形参。 仅限位置形参没有可供外部使用的名称。 在调用接受仅限位置形参的函数时,参数将只根据其位置被映射到形参上。
官方文档参考:
https://docs.python.org/zh-cn/3/faq/programming.html#faq-positional-only-arguments
2 使用
参考python3.9,functools.partial部分源码:
class partial:
"""New function with partial application of the given arguments
and keywords.
"""
__slots__ = "func", "args", "keywords", "__dict__", "__weakref__"
def __new__(cls, func, /, *args, **keywords):
if not callable(func):
raise TypeError("the first argument must be callable")
if hasattr(func, "func"):
args = func.args + args
keywords = {**func.keywords, **keywords}
func = func.func
self = super(partial, cls).__new__(cls)
self.func = func
self.args = args
self.keywords = keywords
return self
def __call__(self, /, *args, **keywords):
keywords = {**self.keywords, **keywords}
return self.func(*self.args, *args, **keywords)
可以看到如下的函数形参定义方式:
def __new__(cls, func, /, *args, **keywords)
def __call__(self, /, *args, **keywords)
结合前述,函数形参列表中的斜杠,表示:在斜杠之前的形参都是仅限位置形参。同时,函数形参列表中的斜杠不会占据参数解构的位置,也就是说,去掉斜杠的效果和带上斜杠的参数接收效果一致,区别仅是带上斜杠的参数列表,有限制其前面的参数,必须为位置形参。
举例如下:
(2.1)内置函数divmod举个栗子:
源码如下所示:
def divmod(x, y): # known case of builtins.divmod
""" Return the tuple (x//y, x%y). Invariant: div*y + mod == x. """
return (0, 0)
使用举例:
print(help(divmod))
print(divmod(11, 2))
结果如下,divmod返回的是元组,元组第一个值是x整除y的结果,第二个值是x除以y取余:
上述divmod函数,参数列表也带有斜杠,说明之前的参数x和y,必须为位置参数(也就是我们常用的*args),而不能是关键字参数(也就是我们常用的**kwargs):
print(divmod(x=11, y=1))
执行报错,TypeError: divmod() takes no keyword arguments:
同理,下述也是不行的:
print(divmod(11, y=1))
即便改换下述保留x和y位置参数,增加额外的关键字参数也是不行的:
print(divmod(11, 1, z=11))
执行依然报错:
(2.2)自定义函数举个栗子:
注意,当前演示代码,为python3.9版本:
第一个栗子:
def printC(x, /, *args, **kwargs):
print(f"参数依次为: {x}, {args}, {kwargs}.")
printC(1, 2, 3, sum=10)
结果如下:
更换参数,执行下述代码:
printC(1, x=2, y=1, sum=10)
结果如下:
下述的写法是有问题的,因为斜杠parameter必须先于(precede)* parameter:
同理下述也是错误的:
下述也会报错(第一个位置必须是位置参数,不能使用关键字参数):
printC(x=2, y=1, sum=10)
执行报错:
第二个栗子:
自定义函数变例,斜杠前有含有默认值的参数:
def printC(x=1, /, y=2):
print(f"参数依次为: {x}, {y}.")
printC(4, 5)
printC(6)
printC(y=9)
执行结果如下:
但是下述执行会抛错,因为第一个参数不能使用关键字参数x=?:
printC(x=9)
结果如下,报错TypeError: printC() got some positional-only arguments passed as keyword arguments: ‘x’:
第三个栗子:
斜杠前,有位置参数和含有默认值的参数:
def printC(z, x=1, /, y=2):
print(f"参数依次为: {z}, {x}, {y}.")
printC(9, 8, 7)
printC(8, 7)
printC(7)
执行结果如下:
但是因为斜杠限制了前面的两个参数,都必须为位置参数,如下会抛出异常:
printC(7, x=8)
结果如下,依然抛出异常:
小结:
上述参数列表的解构赋值可知,参数列表中的斜杠是不会占据实际参数的,仅表明斜杠之前的形参必须为位置形参(斜杠前的形参,不论有无默认值,都必须使用位置参数,不可使用关键字参数)。如果参数列表中我们使用下划线,那么下划线是会占据参数的。