Python 最好的特性之一是提供了极为灵活的参数处理机制,而且Python3进一步提供了keyword-only 参数。与之密切相关的是,调用函数时使用*, **展开可迭代对象,映射到单个参数。
下面通过代码示例展示这些特性:
def tag(name, *content, cls=None, **attrs): """ Generate one or more HTML tags :return: """ if cls is not None: attrs['class'] = cls if attrs: attrs_str = ''.join(' %s = %s' % (attr, value) for attr, value in sorted(attrs.items())) else: attrs_str = '' if content: return ' '.join('<%s%s>%s</%s>' % (name, attrs_str, c, name) for c in content) else: return '<%s%s />' % (name, attrs_str)
上面定义的tag函数的参数:
(1)name是定位参数(Positional argument);
(2)调用tag函数传入的任意个参数被content捕获,content是元组;
(3) cls是关键字参数(Keyword arguments);
(4)可以使用字典作为参数传入函数,字典中的所有元素作为单个参数,同名键会绑定到对应的具名参数,余下的则被**attrs捕获。
接下来我们看看tag函数众多的调用方式:
(1)
>>> tag('br') '<br />'
传入单个参数,'br'传入name
(2)
>>> tag('p', 'hello', 'world') '<p>hello</p> <p>world</p>
第一个参数传入name,第一个参数后面的任意个参数被content捕获,并且是作为元组传入
(3)
>>> tag('p', 'hello', id=33) '<p id = 33>hello</p>'
tag函数中没有明确指定名称的关键字参数会被**attrs捕获,并且是作为字典传入
(4)
>>> tag('p', 'hello', cls='sidebar') '<p class = sidebar>hello</p>'
cls参数只能作为关键字参数传入,它一定不会捕获未命名的定位参数
(5)
>>> tag(content='testing', name='img') '<img content = testing />'
即便第一个定位参数也能作为关键字参数传入
(6)
>>> my_tag = {'name': 'img', 'title': 'Sunset Boulevard', 'src': 'sunset.jpg', 'cls': 'framed'} >>> tag(**my_tag) '<img class = framed src = sunset.jpg title = Sunset Boulevard />'
在字典my_tag前加上**作为单个参数传入,同名键绑定到对应的具名参数上,其余的被**attrs捕获。
需要注意的是,定义函数时,若想指定仅限关键字参数,比如上面的cls,要把它们放到前面有*的参数后。
如果不想支持数量不定的定位参数,但是想支持仅限关键字参数,在签名前放一个*,如下所示:
>>> def f(a, *, b): ... return a, b ... >>> f(1, b=2) (1, 2)