参数处理机制
用一个例子来看 Python 的函数参数处理机制。
Python3 提供了仅限关键词参数( keyword-only arguement
)。
- 用
*
可迭代对象, - 用
**
表示映射到单个参数
def tag(name,*content,cls=None,**attrs):
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 '\n'.join('<%s%s>%s</%s>')%(name,attr_str,c,name) for c in content)
else:
return '<%s%s /> '%(name,attr_str)r)
调用 tag
In [2]: tag('br') # 传入单个定位参数,生成一个指定名称的空标签。
Out[2]: '<br />'
In [3]: tag('br','hello') # 第一个参数后面的任意个参数会被 *content 捕获,存入一个元组。
Out[3]: '<br>hello</br>'
In [4]: print(tag('p','hello','world')) #
<p>hello</p>
<p>world</p>
In [5]: tag('p', 'hello', id=33) # tag 函数签名中没有明确指定名称的关键字参数会被 **attrs 捕获,存入一个字典。
Out[5]: '<p id="33">hello</p>'
In [6]: print(tag('p','hello','world',cls='sidebar')) # cls 参数只能作为关键字参数传入。
<p class="sidebar">hello</p>
<p class="sidebar">world</p>
In [7]: tag(content="testing",name="img") # 调用 tag 函数时,即便第一个定位参数也能作为关键字参数传入。
Out[7]: '<img content="testing" />'
In [8]: my_tag = {'name':'img', 'title':'Sunset Boulevard',
...: 'src':'sunset.jpg','cls':'framed'}
In [9]: tag(**my_tag) # 在 my_tag 前面加上 **,字典中的所有元素作为单个参数传入,同名键会绑定到对应的具名参数上,余下的则被 **attrs 捕获。
Out[9]: '<img class="framed" src="sunset.jpg" title="Sunset Boulevard" />'
总结一下:
- *content 存入一个元组
- cls=None 为仅限关键字参数,传入时需要指定 cls=
- **attrs 其他没有指定的关键字参数,都被存为字典attrs
- 调用时使用 **dirt 表明这是一个字典
定义函数时若想指定仅限关键字参数,要把它们放到前面有 * 的参数后面。如果不想支持数量不定的定位参数,但是想支持仅限关键字参数,在签名中放一个 * :
>>> def f(a, *, b): # 仅限关键字参数不一定要有默认值,强制必须传入实参.
... return a, b
...
>>> f(1, b=2)
(1, 2)
def f(a,*,b,c)
的话,b,c 均为仅限关键字参数。
ps.特别注意 *content 存入的是元组 turple ,以前都当列表处理。
函数签名对象
表示调用函数的方式,即定义了函数的输入和输出。
在Python中,可以使用标准库inspect的一些方法或类,来操作或创建函数签名。
# 注意是小写的signature
from inspect import signature
>>> signature(sum)
<Signature (iterable, start=0, /)>
>>>