《流畅的 Python 》第 5 章笔记

示例 5-10 这段代码有点费解。

def tag(name, *content, cls=None, **attrs): // ①
    """生成一个或多个 HTML 标签"""
    if cls is not None:
        attrs['class'] = cls
    if attrs: // ②
        attr_str = ''.join(' %s="%s"'%(attr, value)
                           for attr, value
                           in sorted(attrs.items()))
    else:
        attr_str = ''
    if content: // ③
        return '
'.join('<%s%s>%s</%s>'%
                         (name, attr_str, c, name) for c in content)
    else:
        return '<%s%s />'%(name, attr_str)
print(tag('br'))
print(tag('p', 'hello'))
print(tag('p', 'hello', 'world'))
print(tag('p', 'hello', id=33))
print(tag('p', 'hello', 'world', cls='sidebar'))
print(tag(content='testing', name='img'))
my_tag = {'name':'img', 'title':'Sunset Boulevard', 'src':'sunset.jpg', 'cls':'framed'}
print(tag(**my_tag))

输出:
content ()
<br />
content ('hello',)
<p>hello</p>
content ('hello', 'world')
<p>hello</p>
<p>world</p>
content ('hello',)
<p id="33">hello</p>
content ('hello', 'world')
<p class="sidebar">hello</p>
<p class="sidebar">world</p>
content ()
<img content="testing" />
content ()
<img class="framed" src="sunset.jpg" title="Sunset Boulevard" />

① 这里的 * 和 ** 代表包裹传递。具体可以参见这篇:https://www.cnblogs.com/vamei/archive/2012/07/08/2581264.html

② 参数 attrs 类型是字典,默认为 {},所以 bool(attrs)False,反之则为 True

③ 参数 content 类型是元组,默认为 (),所以 bool(content)False,反之则为 True

所以这个函数在调用时真正必需的参数只有 name。

我们知道,在参数的几种传递方式混合使用的情况下,在定义或者调用参数时,要注意一个顺序的基本原则:先位置,再关键字,再包裹位置,再包裹关键字。

回到书中这个例子,由于这个函数是 “位置传递”、“包裹位置传递”、“关键字传递”、“包裹关键字传递” 的顺序,所以,在了解书中的几种乱序情况下,我们还需要记住,我们按照参数定义的顺序进行调用时,要小心行事。

原文地址:https://www.cnblogs.com/fanlumaster/p/14427652.html