示例 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。
我们知道,在参数的几种传递方式混合使用的情况下,在定义或者调用参数时,要注意一个顺序的基本原则:先位置,再关键字,再包裹位置,再包裹关键字。
回到书中这个例子,由于这个函数是 “位置传递”、“包裹位置传递”、“关键字传递”、“包裹关键字传递” 的顺序,所以,在了解书中的几种乱序情况下,我们还需要记住,我们按照参数定义的顺序进行调用时,要小心行事。