Python: 深入Python函数定义
May 28, 2015
在Python中,你也可以定义包含若干参数的函数。这里有三种可用的形式,也可以混合使用。
Table of Contents
1. 默认参数值
最常用的一种形式是为一个或多个参数指定默认值。这会创建一个可以使用比定义时允许的参数更少的参数调用的函数,例如:
def ask_ok(prompt, retries = 4, complaint = "Yes or no, please!>"): while True: ok = input(prompt) if ok in ('y', 'ye', 'yes'): return True if ok in ('n' ,'no', 'nop', 'nope'): return False retries = retries - 1 if retries < 0: raise IOError('refusenik user') print(complaint) [/code] <p>这个函数可以通过几种不同的方式调用:</p> <ul> <li> 只给出必要的参数: <b1>ask_ok('Do you really wnat to quit?')</b1></li> <li> 只给出一个可选的参数: <b1>ask_ok('Ok to overwrite the file',2)</b1></li> <li> 或者给出所有的参数: <b1>ask_ok('OK to overwrite the file?',2,'Come on, only yes or no!'),</b1></li> </ul> <p> 这个例子还介绍了 <b1>in</b1>关键字。它测定序列中是否包含某个确定的值: <b1>ok in ('y', 'ye', 'yes')</b1></p> <p>默认值在函数定义作用被解析,如下所示:</p> <pre><code>i = 5 def f(arg = i): print(arg) i = 6 f()</code></pre> <p> 将会输出 <b1>5</b1></p> <p> 重要警告:默认值只被赋值一次。这使得当默认值是可变对象时会有所不同,比如列表、字典或者大多数类的实例。例如,下面的函数在后续调用过程中会累积(前面)付给它的参数: </p> def f(a, L = []): L.append(a) return L print(f(1)) print(f(2)) print(f(3))
这将输出:
[1]
[1, 2]
[1, 2, 3]
如果你不想让默认值在后续调用中累积,你可以像下面一样定义函数:
def f(a, L=None): if L is None: L = [] L.append(a) return L
2. 关键字参数
函数可以通过关键字参数的形式来调用,形如
def parrot(voltage, state = 'a stiff', action = 'voom', type = 'Norwegian Blue'):
接受一个必选的参数(
parrot(1000) parrot(voltage = 1000) parrot(voltage = 10000, action = 'VOOOM') parrot(action = 'VOOOOM', voltage = 1000) # action 写在前面也是OK的! parrot('a million', 'bereft of life', 'jump') # voltage = 'a milion' parrot('a thousand', state = 'pushing up the daisies') # voltage = 'a thousand'
不过以下几种调用是无效的:
parrot() # voltage必须有值 parrot(voltage = 5.0, 'dead') # 一旦有一个参数是通过关键字指定的,后面的也必须都是 parrot(110, voltage = 220) # 两个voltage的值 parrot(acotr = 'Jonh Cleese') # 没有voltage的值
通常,参数列表必须(先书写)位置参数然后才是关键字参数,这里关键字必须来自于形参名字。形参是否有一个默认值并不重要。任何参数都不能被多次赋值——在同一个调用中,与位置参数相同的形参名字不能用作关键字。
引入一个形如
def cheeseshop(kind, *arguments, **keywords): print("-- Do you have any>", kind, "?>") print("-- I'm sorry, we're all out of>", kind) for arg in arguments: print(arg) print("->"*40) # 打印40个’-‘ keys = sorted(keywords.keys()) # 按键值排序 for kw in keys: print(kw, ":>", keywords[kw])
它可以像这样调用:
cheeseshop("Limburger>", "It's very runny, sir.>", "It's really very, VERY runny, sir.>", shopkeeper="Michael Palin>", client="John Cleese>", sketch="Cheese Shop Sketch>")
3. 可变参数列表
最后,一个最不常用的选择是可以让函数调用可变个数的参数。这些参数被包装进一个元组。在这些可变个数的参数之前,可以有零到多个普通的参数:
def write_multiple_items(file, separator, *args): file.write(separator.join(args)) # 用separator符号将arg里的内容连在一起
通常这些可变参数是参数列表的最后一个,因为它们将所有剩余的输入参数传递给函数。任何出现在
>>> def concat(*args, sep="/>"): ... return sep.join(args) ... >>> concat("earth>", "mars>", "venus>") 'earth/mars/venus' >>> concat("earth>", "mars>", "venus>", sep=".>") 'earth.mars.venus'
4. 参数列表的分拆
另有一种相反的情况:当你要传递的参数已经是一个列表,但是要调用的函数却接受分开一个个的参数值,这时候你要把已有的列表拆开来,例如内建函数
>>>list(range(3, 6)) [3, 4 ,5] >>> args = [3, 6] >>> list(range(*args)) [3, 4, 5]
以同样的方式,可以使用
>>> def parrot(voltage, state='a stiff', action='voom'): ... print("-- This parrot wouldn't>", action, end=' ') ... print("if you put>", voltage, "volts through it.>", end=' ') ... print("E's>", state, "!>") ... >>> d = {"voltage>": "four million>", "state>": "bleedin' demised>", "action>": "VOOM>"} >>> parrot(**d) -- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !
5. Lambda形式
出于实际需要,有几种通常在函数式编程语言例如 Lisp 中出现的功能加入到了 Python。通过
>>> def make_incrementor(n): ... return lambda x: x + n ... >>> f = make_incrementor(42) >>> f(0) 42 >>> f(1) 43
0 Comments