1.2.4. 定义函数

1.2.4.1. 函数定义

In [56]: def test():
....: print('in test function')
....:
....:
In [57]: test()
in test function

Warning

函数代码块必须和其他控制流代码块一样缩进。

1.2.4.2. 返回语句

函数可以可选地返回值。

In [6]: def disk_area(radius):
...: return 3.14 * radius * radius
...:
In [8]: disk_area(1.5)
Out[8]: 7.0649999999999995

Note

By default, functions return None.

Note

Note the syntax to define a function:

  • the def keyword;
  • is followed by the function’s name, then
  • 函数的参数在括号中,括号后面有一个冒号。
  • the function body;
  • return object用于可选择地返回值。

1.2.4.3. 参数

Mandatory parameters (positional arguments)

In [81]: def double_it(x):
....: return x * 2
....:
In [82]: double_it(3)
Out[82]: 6
In [83]: double_it()
---------------------------------------------------------------------------
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: double_it() takes exactly 1 argument (0 given)

Optional parameters (keyword or named arguments)

In [84]: def double_it(x=2):
....: return x * 2
....:
In [85]: double_it()
Out[85]: 4
In [86]: double_it(3)
Out[86]: 6

关键字参数允许你指定默认值

Warning

Default values are evaluated when the function is defined, not when it is called. 当使用可变类型(例如字典或列表)并在函数体中修改它们时,这可能是有问题的,因为修改将在函数的每次调用之间持续存在。

Using an immutable type in a keyword argument:

In [124]: bigx = 10
In [125]: def double_it(x=bigx):
.....: return x * 2
.....:
In [126]: bigx = 1e9 # Now really big
In [128]: double_it()
Out[128]: 20

Using an mutable type in a keyword argument (and modifying it inside the function body):

In [2]: def add_to_dict(args={'a': 1, 'b': 2}):
...: for i in args.keys():
...: args[i] += 1
...: print args
...:
In [3]: add_to_dict
Out[3]: <function __main__.add_to_dict>
In [4]: add_to_dict()
{'a': 2, 'b': 3}
In [5]: add_to_dict()
{'a': 3, 'b': 4}
In [6]: add_to_dict()
{'a': 4, 'b': 5}

更多实现python切片的相关示例:

In [98]: def slicer(seq, start=None, stop=None, step=None):
....: """Implement basic python slicing."""
....: return seq[start:stop:step]
....:
In [101]: rhyme = 'one fish, two fish, red fish, blue fish'.split()
In [102]: rhyme
Out[102]: ['one', 'fish,', 'two', 'fish,', 'red', 'fish,', 'blue', 'fish']
In [103]: slicer(rhyme)
Out[103]: ['one', 'fish,', 'two', 'fish,', 'red', 'fish,', 'blue', 'fish']
In [104]: slicer(rhyme, step=2)
Out[104]: ['one', 'two', 'red', 'blue']
In [105]: slicer(rhyme, 1, step=2)
Out[105]: ['fish,', 'fish,', 'fish,', 'fish']
In [106]: slicer(rhyme, start=1, stop=4, step=2)
Out[106]: ['fish,', 'fish,']

The order of the keyword arguments does not matter:

In [107]: slicer(rhyme, step=2, start=1, stop=4)
Out[107]: ['fish,', 'fish,']

but it is good practice to use the same ordering as the function’s definition.

Keyword arguments are a very convenient feature for defining functions with a variable number of arguments, especially when default values are to be used in most calls to the function.

1.2.4.4. 按值传递

Can you modify the value of a variable inside a function? 大多数语言(C、Java,...)区分“传递值”和“通过引用传递”。在Python中,这样的区别是有点人为的,你的变量是否将被修改有点微妙。Fortunately, there exist clear rules.

Parameters to functions are references to objects, which are passed by value. When you pass a variable to a function, python passes the reference to the object to which the variable refers (the value). Not the variable itself.

If the value passed in a function is immutable, the function does not modify the caller’s variable. If the value is mutable, the function may modify the caller’s variable in-place:

>>> def try_to_modify(x, y, z):
... x = 23
... y.append(42)
... z = [99] # new reference
... print(x)
... print(y)
... print(z)
...
>>> a = 77 # immutable variable
>>> b = [99] # mutable variable
>>> c = [28]
>>> try_to_modify(a, b, c)
23
[99, 42]
[99]
>>> print(a)
77
>>> print(b)
[99, 42]
>>> print(c)
[28]

Functions have a local variable table called a local namespace.

The variable x only exists within the function try_to_modify.

1.2.4.5. 全局变量

Variables declared outside the function can be referenced within the function:

In [114]: x = 5
In [115]: def addx(y):
.....: return x + y
.....:
In [116]: addx(10)
Out[116]: 15

But these “global” variables cannot be modified within the function, unless declared global in the function.

这不会改变X:

In [117]: def setx(y):
.....: x = y
.....: print('x is %d' % x)
.....:
.....:
In [118]: setx(10)
x is 10
In [120]: x
Out[120]: 5

这将改变X:

In [121]: def setx(y):
.....: global x
.....: x = y
.....: print('x is %d' % x)
.....:
.....:
In [122]: setx(10)
x is 10
In [123]: x
Out[123]: 10

1.2.4.6. 可变数量的参数

Special forms of parameters:
  • *args:任意数量的位置参数,封装到一个元组中
  • **kwargs:任意数量的关键字参数,封装在一个字典中
In [35]: def variable_args(*args, **kwargs):
....: print 'args is', args
....: print 'kwargs is', kwargs
....:
In [36]: variable_args('one', 'two', x=1, y=2, z=3)
args is ('one', 'two')
kwargs is {'y': 2, 'x': 1, 'z': 3}

1.2.4.7. Docstrings

Documentation about what the function does and its parameters. General convention:

In [67]: def funcname(params):
....: """Concise one-line sentence describing the function.
....:
....: Extended summary which can contain multiple paragraphs.
....: """
....: # function body
....: pass
....:
In [68]: funcname?
Type: function
Base Class: type 'function'>
String Form: <function funcname at 0xeaa0f0>
Namespace: Interactive
File: <ipython console>
Definition: funcname(params)
Docstring:
Concise one-line sentence describing the function.
Extended summary which can contain multiple paragraphs.

Note

Docstring指南

For the sake of standardization, the Docstring Conventions webpage documents the semantics and conventions associated with Python docstrings.

此外,Numpy和Scipy模块定义了用于文档化科学计算函数的精确标准,你可能想要让你自己的函数遵从它们,例如使用Parameters部分、Examples部分,等等。See http://projects.scipy.org/numpy/wiki/CodingStyleGuidelines#docstring-standard and http://projects.scipy.org/numpy/browser/trunk/doc/example.py#L37

1.2.4.8. 函数是对象

函数是第一等对象,这意味着它们可以:
  • 赋值给一个变量
  • 列表(或任何集合)中的元素
  • passed as an argument to another function.
In [38]: va = variable_args
In [39]: va('three', x=1, y=2)
args is ('three',)
kwargs is {'y': 2, 'x': 1}

1.2.4.9. 方法

方法是附属在对象上的函数。你已在我们的列表字典字符串...等示例中看到这些内容。

1.2.4.10. 练习

Exercise: Fibonacci sequence

编写一个函数,显示Fibonacci序列的前n项,定义如下:

  • u_0 = 1; u_1 = 1
  • u_(n+2) = u_(n+1) + u_n

Exercise: Quicksort

Implement the quicksort algorithm, as defined by wikipedia

function quicksort(array)
var list less, greater
if length(array) < 2
return array
select and remove a pivot value pivot from array
for each x in array
if x < pivot + 1 then append x to less
else append x to greater
return concatenate(quicksort(less), pivot, quicksort(greater))