函数以关键字def
定义,其后紧跟函数名,由一对小括号闭合的形参,最后以冒号结束定义行,定义行下面的是函数体,它是一个语句块。
1 | #!/usr/bin/python |
1 | $ python function1.py |
形参在函数定义中的小括号内指定,并以逗号分隔。当我们调用函数时以同样的方式提供形参值。
1 | #!/usr/bin/python |
1 | $ python func_param.py |
在函数内声明的变量与在函数外的同名变量没有任何关系,即变量名对于函数是局部的。
这被称作变量的作用域,变量的作用域开始于它们所在块中定义它们的定义点处。
1 | #!/usr/bin/python |
1 | $ python func_local.py |
如果你想要为一个定义在函数外的变量赋值,那么你就得告诉Python这个变量名不是局部的,而是 全局 的。我们使用global语句完成这一功能。没有global语句,是不可能为定义在函数外的变量赋值的。
你可以使用定义在函数外的变量的值(假设在函数内没有同名的变量)。然而,我并不鼓励你这样做,并且你应该尽量避免这样做,因为这使得程序的读者会不清楚这个变量是在哪里定义的。使用global语句可以清楚地表明变量是在外面的块定义的。
1 | #!/usr/bin/python |
1 | $ python func_global.py |
我们已经看到如何存取局部和全局变量。还有另一类叫做 非局部 的作用域,它介于局部和全局之间。
当在函数内定义函数时你会注意到非局部作用域。
因为python中的一切只是可执行代码,所以你可以在任何地方定义函数。让我们看一个例子:
1 | #!/usr/bin/python |
1 | $ python func_nonlocal.py |
当我们处于func_inner
函数中时,func_outer
第一行定义的变量x既不是局部也不是全局变量。
这时通过nonlocal x
我们声明这个x
是非局部的,所以我们才能够存取它。
试着将nonlocal x
改为global x
观察这两种用法有什么不同。
对于一些函数,你可能希望它们的形参是可选的,并当用户没有为这些形参提供值的时候给它们一个默认值。
这需要借助默认实参值。默认实参值在函数定义时通过为形参名赋一个默认值实现。
1 | #!/usr/bin/python |
1 | $ python func_default.py |
只有在实参列表靠后的参数才能拥有默认实参值 ,即你不能先声明带有默认实参值的形参再声明不带有默认实参值的参数。
这是因为实参值是根据形参的位置赋给形参的,例如:def func(a, b = 5)
合法,但def func(a = 5, b)
就非法了。
如果你有一些函数拥有许多参数,但你只想使用其中的几个,这时你可以通过形参名为其赋值。
这被称做关键实参——使用形参名(关键字)为函数指定实参而不是我们一直使用的通过位置指定实参。
这样做有两个优点,首先函数用起来更简单,因为我们不用操心实参的顺序了。
其次,可以只为我们感兴趣的形参赋值,如果其它参数带有默认实参值的话。
1 | #!/usr/bin/python |
1 | $ python func_key.py |
有时你可能希望编写一个可以接受任意多个形参的函数,使用星号可以帮你做到。
1 | #!/usr/bin/python |
1 | $ python total.py |
星号-列表:当我们以 星号 声明一个形参比如*param
,那么这个参数点之后的所有实参会被收集成一个列表。
双星号-关键字实参字典:与之类似如果我们以 双星号 声明一个形参,它会被收集成一个关键字实参字典。
如果我们希望某些关键字形参只能通过关键字实参得到而不是按照实参的位置得到,可以将其声明在星号形参后面。称为Keyword-only实参:
1 | #!/usr/bin/python |
1 | $ python keyword_only.py |
在星号形参后面声明的形参导致它成为keyword-only实参。
如果没有为这些实参提供一个默认值,那么必须在调用函数时以关键字实参为其赋值,否则将引发错误。
如果你只需要keyword-only实参但不需要星号实参,那么可以简单的省略星号实参的实参名。
例如def total(initial=5, *, vegetables)
。
return
用于从函数返回,即跳出函数。也可以利用return
语句从函数返回一个值。
注意一个不带有返回值的return
语句相当于返回return None
。
None
是python的一个特殊类型,代表空。例如如果一个变量的值为None
则代表它不存在值。每个函数的末尾都隐含的包含一个return None
语句除非你编写了自己的return
语句。
1 | #!/usr/bin/python |
1 | $ python func_return.py |
文档字符串(doc string)是一个你应该利用的重要的工具,因为它帮助你更好的注释程序使得程序更易于理解。
更神奇的是你甚至可以在程序运行时取得文档字符串!
1 | #!/usr/bin/python |
1 | $ python func_doc.py |
一个函数的第一个逻辑行的字符串将成为这个函数的文档字符串。注意类和模块同样拥有文档字符串,在后面相应的章节我们会学到它们。
根据惯例:
我强烈建议你在你的正规函数中遵循这个编写文档字符串的惯例。
我们可以通过使用函数的__doc__
属性(注意双下划线)存取printMax的文档字符串。如果你在python使用过help()
,其实你已经看到过文档字符串的应用了!help()只是取出函数的__doc__
属性,然后以一种整洁的方式显示给你。