python学习-函数定义理解

来源:互联网 发布:行知幼稚园 编辑:程序博客网 时间:2024/06/03 13:27

1 深入python函数定义

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

1.1 默认参数值

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

>>> def ask_ok(prompt,retries = 4,complaint='yes or no,please!'):...     while True:...             ok = raw_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 want 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 关键字。它测定序列中是否包含某个确定的值。

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

i = 5def f(arg=i):    print argi = 6f()

将会输出 5

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

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

如果你不想在随后的调用中共享默认值,可以像这样写函数:

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

1.2 关键字参数

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

def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):    print "-- This parrot wouldn't", action,    print "if you put", voltage, "volts through it."    print "-- Lovely plumage, the", type    print "-- It's", state, "!"
接受一个必选参数 ( voltage ) 以及三个可选参数(state ,action , 和 type )。 可以用以下的任一方法调用:

parrot(1000)                                          # 1 positional argumentparrot(voltage=1000)                                  # 1 keyword argumentparrot(voltage=1000000, action='VOOOOOM')             # 2 keyword argumentsparrot(action='VOOOOOM', voltage=1000000)             # 2 keyword argumentsparrot('a million', 'bereft of life', 'jump')         # 3 positional argumentsparrot('a thousand', state='pushing up the daisies')  # 1 positional, 1 keyword
不过以下几种调用是无效的:

parrot()                     # required argument missingparrot(voltage=5.0, 'dead')  # non-keyword argument after a keyword argumentparrot(110, voltage=220)     # duplicate value for the same argumentparrot(actor='John Cleese')  # unknown keyword argument
1.3 可变参数

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

def write_multiple_items(file, separator, *args):    file.write(separator.join(args))

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

>>> def concat(*args, sep="/"):...    return sep.join(args)...>>> concat("earth", "mars", "venus")'earth/mars/venus'>>> concat("earth", "mars", "venus", sep=".")'earth.mars.venus'

注意:我按照此方法行不通。经对比发现,带有*的列表或者**的字典形式参数必须放在后边。上面的例子可以这样实现:

>>> def concat(sep="/",*args):...     return sep.join(args)...

输出:

>>> concat("c","a","b","c")'acbcc'>>> concat(",","a","b","c")'a,b,c'>>> concat(".","a","b","c")'a.b.c'

1.4 参数列表的分拆

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

>>> list(range(3, 6))            # normal call with separate arguments[3, 4, 5]>>> args = [3, 6]>>> list(range(*args))            # call with arguments unpacked from a list[3, 4, 5]

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

>>> def parrot(voltage, state='a stiff', action='voom'):...     print "-- This parrot wouldn't", action,...     print "if you put", voltage, "volts through it.",...     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 !
1.5 Lambda形式

出于实际需要,有几种通常在函数式编程语言例如 Lisp 中出现的功能加入到了 Python 中。通过 lambda 关键字,可以创建短小的匿名函数。这里有一个函数返回它的两个参数的和: lambda a, b:a+b 。 Lambda 形式可以用于任何需要的函数对象。出于语法限制,它们只能有一个单独的表达式。语义上讲,它们只是普通函数定义中的一个语法技巧。类似于嵌套函数定义,lambda 形式可以从外部作用域引用变量:

>>> def make_incrementor(n):...     return lambda x: x + n...>>> f = make_incrementor(42)>>> f(0)42>>> f(1)43
1.6 文档字符串

这里介绍的文档字符串的概念和格式。

第一行应该是关于对象用途的简介。简短起见,不用明确的陈述对象名或类型,因为它们可以从别的途径了解到(除非这个名字碰巧就是描述这个函数操作的动词)。这一行应该以大写字母开头,以句号结尾。

如果文档字符串有多行,第二行应该空出来,与接下来的详细描述明确分隔。接下来的文档应该有一或多段描述对象的调用约定、边界效应等。

Python 的解释器不会从多行的文档字符串中去除缩进,所以必要的时候应当自己清除缩进。这符合通常的习惯。第一行之后的第一个非空行决定了整个文档的缩进格式。(我们不用第一行是因为它通常紧靠着起始的引号,缩进格式显示的不清楚。)留白“相当于”是字符串的起始缩进。每一行都不应该有缩进,如果有缩进的话,所有的留白都应该清除掉。留白的长度应当等于扩展制表符的宽度(通常是8个空格)。

以下是一个多行文档字符串的示例:

>>> def my_function():...     """Do nothing, but document it.......     No, really, it doesn't do anything....     """...     pass...>>> print my_function.__doc__    Do nothing, but document it.    No, really, it doesn't do anything.
1.7 插曲:编码风格

此时你已经可以写一个更长更复杂的 Python 程序,是时候讨论一下 编码风格 了。大多数语言可以写(或者更明白地说,格式化 )作几种不同的风格。有些比其它的更好读。让你的代码对别人更易读是个好想法,养成良好的编码风格对此很有帮助。

对于 Python, PEP 8 引入了大多数项目遵循的风格指导。它给出了一个高度可读,视觉友好的编码风格。每个 Python 开发者都应该读一下,大多数要点都会对你有帮助:

  • 使用 4 空格缩进,而非 TAB。

    在小缩进(可以嵌套更深)和大缩进(更易读)之间,4空格是一个很好的折中。TAB 引发了一些混乱,最好弃用。

  • 折行以确保其不会超过 79 个字符。

    这有助于小显示器用户阅读,也可以让大显示器能并排显示几个代码文件。

  • 使用空行分隔函数和类,以及函数中的大块代码。

  • 可能的话,注释独占一行

  • 使用文档字符串

  • 把空格放到操作符两边,以及逗号后面,但是括号里侧不加空格: a=f(1, 2)+g(3, 4)

  • 统一函数和类命名。

    推荐类名用 驼峰命名, 函数和方法名用小写_和_下划线。总是用self 作为方法的第一个参数(关于类和方法的知识详见初识类 )。

  • 不要使用花哨的编码,如果你的代码的目的是要在国际化环境。 Python 的默认情况下,UTF-8,甚至普通的 ASCII 总是工作的最好。

  • 同样,也不要使用非 ASCII 字符的标识符,除非是不同语种的会阅读或者维护代码。


0 0
原创粉丝点击