Python: 深入Python函数定义

python scott 167℃ 0评论

在Python中,你也可以定义包含若干参数的函数。这里有三种可用的形式,也可以混合使用。

1. 默认参数值

最常用的一种形式是为一个或多个参数指定默认值。这会创建一个可以使用比定义时允许的参数更少的参数调用的函数,例如:

1
2
3
4
5
6
7
8
9
10
11
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)

这个函数可以通过几种不同的方式调用:

  • 只给出必要的参数: ask_ok(‘Do you really wnat to quit?’)
  • 只给出一个可选的参数: ask_ok(‘Ok to overwrite the file’,2)
  • 或者给出所有的参数: ask_ok(‘OK to overwrite the file?’,2,’Come on, only yes or no!’),

这个例子还介绍了 in关键字。它测定序列中是否包含某个确定的值: ok in (‘y’, ‘ye’, ‘yes’)

默认值在函数定义作用被解析,如下所示:


1
2
3
4
5
i = 5
def f(arg = i):
    print(arg)
i = 6
f()

将会输出 5

重要警告:默认值只被赋值一次。这使得当默认值是可变对象时会有所不同,比如列表、字典或者大多数类的实例。例如,下面的函数在后续调用过程中会累积(前面)付给它的参数:

1
2
3
4
5
6
def f(a, L = []):
    L.append(a)
    return L
print(f(1))
print(f(2))
print(f(3))

这将输出:


1
2
3
[1]
[1, 2]
[1, 2, 3]

如果你不想让默认值在后续调用中累积,你可以像下面一样定义函数:

1
2
3
4
5
def f(a, L=None):
    if L is None:
        L = []
    L.append(a)
    return L

2. 关键字参数

函数可以通过关键字参数的形式来调用,形如 keyword = value。例如:以下的函数:

1
def parrot(voltage, state = 'a stiff', action = 'voom', type = 'Norwegian Blue'):

接受一个必选的参数( voltage)以及三个可选参数( state, actiontype)。可以用以下的任一方法调用:

1
2
3
4
5
6
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'

不过以下几种调用是无效的:

1
2
3
4
parrot() # voltage必须有值
parrot(voltage = 5.0, 'dead') # 一旦有一个参数是通过关键字指定的,后面的也必须都是
parrot(110, voltage = 220) # 两个voltage的值
parrot(acotr = 'Jonh Cleese') # 没有voltage的值

通常,参数列表必须(先书写)位置参数然后才是关键字参数,这里关键字必须来自于形参名字。形参是否有一个默认值并不重要。任何参数都不能被多次赋值——在同一个调用中,与位置参数相同的形参名字不能用作关键字。

引入一个形如 **name的参数时,它接收一个字典,该字典包含了所有未出现的形式参数中关键字参数。这里可能还会组合使用一个形如 *name的形式参数,它接收一个元组,包含了所有没有出现在形式参数列表中的参数值( *name必须出现在 **name之前)。例如,我们这样定义一个函数:

1
2
3
4
5
6
7
8
9
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])

它可以像这样调用:

1
2
3
4
5
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. 可变参数列表

最后,一个最不常用的选择是可以让函数调用可变个数的参数。这些参数被包装进一个元组。在这些可变个数的参数之前,可以有零到多个普通的参数:

1
2
def write_multiple_items(file, separator, *args):
    file.write(separator.join(args)) # 用separator符号将arg里的内容连在一起

通常这些可变参数是参数列表的最后一个,因为它们将所有剩余的输入参数传递给函数。任何出现在 args后的参数是关键字参数,这意味着,他们只能被用作关键字,而不是位置参数:

1
2
3
4
5
6
7
>>> def concat(*args, sep="/>"):
...    return sep.join(args)
...
>>> concat("earth>", "mars>", "venus>")
'earth/mars/venus'
>>> concat("earth>", "mars>", "venus>", sep=".>")
'earth.mars.venus'

4. 参数列表的分拆

另有一种相反的情况:当你要传递的参数已经是一个列表,但是要调用的函数却接受分开一个个的参数值,这时候你要把已有的列表拆开来,例如内建函数 range()需要两个独立的参数 range(start, end)。你可以在调用函数时加一个 *把已有的列表拆开:

1
2
3
4
5
>>>list(range(3, 6))
[3, 4 ,5]
>>> args = [3, 6]
>>> list(range(*args))
[3, 4, 5]

以同样的方式,可以使用 **操作符分拆关键字参数为字典:

1
2
3
4
5
6
7
8
>>> 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。通过 lambda关键字,可以创建短小的匿名函数。这里有一个函数返回它的两个参数的和: lambda a, b: a+b。 Lambda 形式可以用于任何需要的函数对象。出于语法限制,它们只能有一个单独的表达式。语义上讲,它们只是普通函数定义中的一个语法技巧。类似于嵌套函数定义,lambda 形式可以从外部作用域引用变量:

1
2
3
4
5
6
7
8
>>> def make_incrementor(n):
...     return lambda x: x + n
...
>>> f = make_incrementor(42)
>>> f(0)
42
>>> f(1)
43

原文:http://www.cnblogs.com/ronny/p/4511747.html

转载请注明:osetc.com » Python: 深入Python函数定义

喜欢 (0)or分享 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址