《摘自流暢的Python》 此書真乃寶書也,雖說還是有點兒沒懂
從定位參數到僅限關鍵字參數
Python最好的特性之一是提供了極為靈活的參數處理機制,而且Python3進一步提供了僅限關鍵字參數(keyword-only argument)。與之密切相關的是,調用函數時使用*和**“展開”可迭代對象,映射到單個參數。下面實例中代碼展示這些特性,實際使用在第二個例子中。
[例5-11] tag函數用于生成HTML標簽,使用名為cls
的關鍵字參數傳入“class”屬性,這是一種變通方法,因為“class”是Python的關鍵字:
def tag(name, *content, cls=None, **attrs):"""生成一個或多個HTML標簽"""if cls is not None:attrs['class'] = clsif attrs:attr_str = ''.join('%s="%s"' % (attr, value)for attr, valuein sorted(attrs.items()))else:attr_str = ''if content:return '\n'.join('<%s%s>%s</%s>' % (name, attr_str, c, name) for c in content)else:return '<%s%s />' % (name, attr_str)
復制代碼
tag 函數的調用方式很多,例子如下:
>>> tag('br') # 傳入單個參數,生成一個指定名稱的空標簽
'<br />'>>> tag('p', 'hello') # 第一個參數后面的任意個參數會被*content捕獲,存到一個數組
'<p>hello</p>'>>> print(tag('p', 'hello', 'world'))
<p>hello</p>
<p>world</p>>>> tag('p', 'hello', id=33)
'<p id=33>hello</p>'
>>> # tag函數簽名中沒有明確指定名稱的關鍵字參數會被**attrs捕獲,存入字典>>> print(tag('p', 'hello', 'world', cls='sidebar')) # cls參數只能作為關鍵字參數傳入
<p class='sidebar'>hello</p>
<p class='sidebar'>world</p>>>> tag(content='testing', name='img') # 調用tag函數,即便第一個定位參數也能作為關鍵字參數傳入
'<img content="testing", name="img">'>>> # 在 my_tag 前面加上**, 字典中的所有元素作為單個參數傳入,
>>> # 同名鍵會綁定到對應的參數具體參數上,其余的則被**attrs 捕獲
>>> my_tag = {'name':'img', 'title':'Sunset Boulevard',
... 'src':'sunset.jpg', 'cls':'framed'}
>>> tag(**my_tag)
'<img class="framed" src="sunset.jpg", title="Sunset Boulevard" />'
復制代碼
僅限關鍵字參數是Python3新增的特性,在上例中,cls
參數只能通過關鍵字參數指定,它一定不會捕獲未命名的定位參數。定義函數時若想指定僅限關鍵字參數,要把它們放到前面*的參數后面。如果不想支持數量不定的定位參數,但是想支持僅限關鍵字參數,在簽名后面放一個*,如下所示:
>>> def f(a, *, b):
... return a, b
>>> f(1, b=2)
(1, 2)
復制代碼
注意,僅限關鍵字參數不一定要有默認值,可以像上例中的b一樣,強制必須傳入實參。
接下來說明函數參數的內省,以一個Web框架中的實例為引子,接著討論內省。