编写可接受任意数量的函数

要编写一个可以接受任意数量的位置参数的函数,我们可以使用以*开头的参数:

def avg(first, *rest):
return (first + sum(rest)) / (1 + len(rest))

在这里,rest是一个元组,它包含了其它所有传递过来的位置参数,代码在之后的计算中会将其视为一个序列来进行处理。当然,如果要接受任意数量的关键字参数,我们可以使用以**开头的参数:

import html
def make_element(name, value, **attrs):
    keyvals = [' %s="%s"' % item for item in attrs.items()]
    attr_str = ''.join(keyvals)
    element = '<{name}{attrs}>{value}</{name}>'.format(
                  name=name,
                  attrs=attr_str,
                  value=html.escape(value))
return element

在这里attrs是一个字典,它包含了所有传递过来的关键字参数。如果想要函数能够同时接受任意数量的位置参数和关键字参数,只要联合使用*和**即可:

def anyargs(*args, **kwargs):
    print(args)
    print(kwargs)

在这个函数中,所有的位置参数都会放置在元组args中,而所有的关键字参数都会放在字典kwargs中。

编写只接受关键字参数的函数

如果将关键字参数放置在以*打头的参数或者是一个单独的*之后,这个特性就很容易实现:

def recv(maxsize, *, block):
    'Receives a message'
    pass

# recv(1024, True) # TypeError
recv(1024, block=True)  # Ok

这项技术也可以用来为那些可接受任意数量的位置参数的函数来指定关键字参数:

def minimum(*values, clip=None):
    m = min(values)
    if clip is not None:
        m = clip if clip > m else m
    return m


minimum(1, 5, 2, -5, 10)  # Returns -5
minimum(1, 5, 2, -5, 10, clip=0)  # Returns 0

当指定可选函数参数的时候,keyword-only参数常常是一种提高代码可读性的好方法。同时,这个参数在更加高级的上下文环境中同样也能起到作用,比如它可以用来为函数注入参数,这些函数利用*args和**kwargs接受所有的输入参数,后面我们会进行详细的解释。

将元素据信息附加到函数参数上

我们已经编写好了一个函数,但是希望能为参数附加上一些额外的信息,这样其他人可以对函数的使用方法有更多的认识和了解。

函数的参数注解可以提示程序员这个函数该怎样使用。Python解释器并不会附加任何语法意义到这些参数注解上,它们既不是检查类型也不会改变Python的行为。但是,参数注解会给其他阅读源代码的人带来有用的提示

参考书目:

《Python CookBook》作者:【美】 David Beazley, Brian K. Jones