Python函数参数处理
Python 函数最好的功能之一是提供了极为灵活的参数处理机制。调用函数时可以使用 *
和 **
拆包可迭代对象,映射各个参数。
仅限关键字参数
def tag(name, *content, class_=None, **attrs):
"""生成一个或多个HTML标签"""
if class_ is not None:
attrs['class'] = class_
attr_pairs = (f' {attr}="{value}"' for attr, value
in sorted(attrs.items()))
attr_str = ''.join(attr_pairs)
if content:
elements = (f'<{name}{attr_str}>{c}</{name}>'
for c in content)
return '\n'.join(elements)
else:
return f'<{name}{attr_str} />'
构造一个tag 函数用于生成 HTML 标签。
可以使用名为 class_ 的仅限关键字参数传入“class”属性
这是一种变通方法,因为“class”是 Python 中的关键字
-
传入单个位置参数,生成一个指定名称的空标签
tag('br') >>>'<br />'
-
传入多个参数,第一个参数后面的任意数量的参数被
*content
捕获,存入一个元组tag('p', 'hello') >>> '<br />' print(tag('p', 'hello', 'world')) >>> <p>hello</p> <p>world</p>
-
tag 函数签名中没有明确指定名称的关键字参数被 **attrs 捕获,存入一个字典。
tag('p', 'hello', id=33) >>> '<p id="33">hello</p>' # class_ 参数只能作为关键字参数传入 print(tag('p', 'hello', 'world', class_='sidebar')) >>> <p class="sidebar">hello</p> <p class="sidebar">world</p>
-
第一个位置参数也能作为关键字参数传入
tag(content='testing', name="img") >>> '<img content="testing" />'
-
在 my_tag 前面加上
**
,字典中的所有项作为参数依次传入
同名键绑定到对应的具名参数上,余下的则被**attrs
捕获。在这个字典中可以使用 ‘class’ 作为键,因为它是字符串,与保留字 class 不冲突
my_tag = {'name': 'img', 'title': 'Sunset Boulevard', 'src': 'sunset.jpg', 'class': 'framed'} tag(**my_tag) >>> '<img class="framed" src="sunset.jpg" title="Sunset Boulevard" />'
在示例中,class_
参数只能通过关键字参数指定,它一定不会捕获无名位置参数。
定义函数时,如果想指定仅限关键字参数,要把它们放到前面有*
的参数后面。
上面例子中
class_
参数放在*content
后面
如果不想支持数量不定的位置参数,但是想支持仅限关键字参数,则可以在签名中放一个*
def f(a, *, b):
return a, b
f(1, b=2)
>>>
(1, 2)
=======================
f(1,2)
>>>
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
----> 1 f(1,2)
TypeError: f() takes 1 positional argument but 2 were given
仅限关键字参数不一定要有默认值,可以像上例中的 b 那样,强制要求传入实参
仅限位置参数
从 Python 3.8 开始,用户定义的函数签名可以指定仅限位置参数。
内置函数都是如此.
如 divmod(a, b) 只能使用位置参数调用,不能写成 divmod(a=10, b=4)
如果想定义只接受位置参数的函数,则可以在参数列表中使用 /
。
/
前边均是仅限位置参数。在/
后面,可以指定其他参数,处理方式一同往常
python3.8之前版本,参数列表中的 / 将导致句法错误
def divmod(a, b, /):
return (a // b, a % b)
divmod(1,2)
>>>
(0, 1)
divmod(a=1,b=2)
>>>
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
----> 1 divmod(a=1,b=2)
TypeError: divmod() got some positional-only arguments passed as keyword arguments: 'a, b'
对于上面 tag 函数,如果希望 name 是仅限位置参数,可以在函数签名中添加一个 /
,如下所示。
def tag(name, /, *content, class_=None, **attrs):
...