mirror of
https://github.com/apachecn/ailearning.git
synced 2026-02-03 10:24:39 +08:00
436 lines
6.4 KiB
Markdown
436 lines
6.4 KiB
Markdown
# 函数
|
||
|
||
## 定义函数
|
||
|
||
函数`function`,通常接受输入参数,并有返回值。
|
||
|
||
它负责完成某项特定任务,而且相较于其他代码,具备相对的独立性。
|
||
|
||
In [1]:
|
||
|
||
```py
|
||
def add(x, y):
|
||
"""Add two numbers"""
|
||
a = x + y
|
||
return a
|
||
|
||
```
|
||
|
||
函数通常有一下几个特征:
|
||
|
||
* 使用 `def` 关键词来定义一个函数。
|
||
* `def` 后面是函数的名称,括号中是函数的参数,不同的参数用 `,` 隔开, `def foo():` 的形式是必须要有的,参数可以为空;
|
||
* 使用缩进来划分函数的内容;
|
||
* `docstring` 用 `"""` 包含的字符串,用来解释函数的用途,可省略;
|
||
* `return` 返回特定的值,如果省略,返回 `None` 。
|
||
|
||
## 使用函数
|
||
|
||
使用函数时,只需要将参数换成特定的值传给函数。
|
||
|
||
**Python**并没有限定参数的类型,因此可以使用不同的参数类型:
|
||
|
||
In [2]:
|
||
|
||
```py
|
||
print add(2, 3)
|
||
print add('foo', 'bar')
|
||
|
||
```
|
||
|
||
```py
|
||
5
|
||
foobar
|
||
|
||
```
|
||
|
||
在这个例子中,如果传入的两个参数不可以相加,那么**Python**会将报错:
|
||
|
||
In [3]:
|
||
|
||
```py
|
||
print add(2, "foo")
|
||
|
||
```
|
||
|
||
```py
|
||
---------------------------------------------------------------------------
|
||
TypeError Traceback (most recent call last)
|
||
<ipython-input-3-6f8dcf7eb280> in <module>()
|
||
----> 1 print add(2, "foo")
|
||
|
||
<ipython-input-1-e831943cfaf2> in add(x, y)
|
||
1 def add(x, y):
|
||
2 """Add two numbers"""
|
||
----> 3 a = x + y
|
||
4 return a
|
||
|
||
TypeError: unsupported operand type(s) for +: 'int' and 'str'
|
||
```
|
||
|
||
如果传入的参数数目与实际不符合,也会报错:
|
||
|
||
In [4]:
|
||
|
||
```py
|
||
print add(1, 2, 3)
|
||
|
||
```
|
||
|
||
```py
|
||
---------------------------------------------------------------------------
|
||
TypeError Traceback (most recent call last)
|
||
<ipython-input-4-ed7bae31fc7d> in <module>()
|
||
----> 1 print add(1, 2, 3)
|
||
|
||
TypeError: add() takes exactly 2 arguments (3 given)
|
||
```
|
||
|
||
In [5]:
|
||
|
||
```py
|
||
print add(1)
|
||
|
||
```
|
||
|
||
```py
|
||
---------------------------------------------------------------------------
|
||
TypeError Traceback (most recent call last)
|
||
<ipython-input-5-a954233d3b0d> in <module>()
|
||
----> 1 print add(1)
|
||
|
||
TypeError: add() takes exactly 2 arguments (1 given)
|
||
```
|
||
|
||
传入参数时,Python提供了两种选项,第一种是上面使用的按照位置传入参数,另一种则是使用关键词模式,显式地指定参数的值:
|
||
|
||
In [6]:
|
||
|
||
```py
|
||
print add(x=2, y=3)
|
||
print add(y="foo", x="bar")
|
||
|
||
```
|
||
|
||
```py
|
||
5
|
||
barfoo
|
||
|
||
```
|
||
|
||
可以混合这两种模式:
|
||
|
||
In [7]:
|
||
|
||
```py
|
||
print add(2, y=3)
|
||
|
||
```
|
||
|
||
```py
|
||
5
|
||
|
||
```
|
||
|
||
## 设定参数默认值
|
||
|
||
可以在函数定义的时候给参数设定默认值,例如:
|
||
|
||
In [8]:
|
||
|
||
```py
|
||
def quad(x, a=1, b=0, c=0):
|
||
return a*x**2 + b*x + c
|
||
|
||
```
|
||
|
||
可以省略有默认值的参数:
|
||
|
||
In [9]:
|
||
|
||
```py
|
||
print quad(2.0)
|
||
|
||
```
|
||
|
||
```py
|
||
4.0
|
||
|
||
```
|
||
|
||
可以修改参数的默认值:
|
||
|
||
In [10]:
|
||
|
||
```py
|
||
print quad(2.0, b=3)
|
||
|
||
```
|
||
|
||
```py
|
||
10.0
|
||
|
||
```
|
||
|
||
In [11]:
|
||
|
||
```py
|
||
print quad(2.0, 2, c=4)
|
||
|
||
```
|
||
|
||
```py
|
||
12.0
|
||
|
||
```
|
||
|
||
这里混合了位置和指定两种参数传入方式,第二个2是传给 `a` 的。
|
||
|
||
注意,在使用混合语法时,要注意不能给同一个值赋值多次,否则会报错,例如:
|
||
|
||
In [12]:
|
||
|
||
```py
|
||
print quad(2.0, 2, a=2)
|
||
|
||
```
|
||
|
||
```py
|
||
---------------------------------------------------------------------------
|
||
TypeError Traceback (most recent call last)
|
||
<ipython-input-12-101d0c090bbb> in <module>()
|
||
----> 1 print quad(2.0, 2, a=2)
|
||
|
||
TypeError: quad() got multiple values for keyword argument 'a'
|
||
```
|
||
|
||
## 接收不定参数
|
||
|
||
使用如下方法,可以使函数接受不定数目的参数:
|
||
|
||
In [13]:
|
||
|
||
```py
|
||
def add(x, *args):
|
||
total = x
|
||
for arg in args:
|
||
total += arg
|
||
return total
|
||
|
||
```
|
||
|
||
这里,`*args` 表示参数数目不定,可以看成一个元组,把第一个参数后面的参数当作元组中的元素。
|
||
|
||
In [14]:
|
||
|
||
```py
|
||
print add(1, 2, 3, 4)
|
||
print add(1, 2)
|
||
|
||
```
|
||
|
||
```py
|
||
10
|
||
3
|
||
|
||
```
|
||
|
||
这样定义的函数不能使用关键词传入参数,要使用关键词,可以这样:
|
||
|
||
In [15]:
|
||
|
||
```py
|
||
def add(x, **kwargs):
|
||
total = x
|
||
for arg, value in kwargs.items():
|
||
print "adding ", arg
|
||
total += value
|
||
return total
|
||
|
||
```
|
||
|
||
这里, `**kwargs` 表示参数数目不定,相当于一个字典,关键词和值对应于键值对。
|
||
|
||
In [16]:
|
||
|
||
```py
|
||
print add(10, y=11, z=12, w=13)
|
||
|
||
```
|
||
|
||
```py
|
||
adding y
|
||
adding z
|
||
adding w
|
||
46
|
||
|
||
```
|
||
|
||
再看这个例子,可以接收任意数目的位置参数和键值对参数:
|
||
|
||
In [17]:
|
||
|
||
```py
|
||
def foo(*args, **kwargs):
|
||
print args, kwargs
|
||
|
||
foo(2, 3, x='bar', z=10)
|
||
|
||
```
|
||
|
||
```py
|
||
(2, 3) {'x': 'bar', 'z': 10}
|
||
|
||
```
|
||
|
||
不过要按顺序传入参数,先传入位置参数 `args` ,在传入关键词参数 `kwargs` 。
|
||
|
||
## 返回多个值
|
||
|
||
函数可以返回多个值:
|
||
|
||
In [18]:
|
||
|
||
```py
|
||
from math import atan2
|
||
|
||
def to_polar(x, y):
|
||
r = (x**2 + y**2) ** 0.5
|
||
theta = atan2(y, x)
|
||
return r, theta
|
||
|
||
r, theta = to_polar(3, 4)
|
||
print r, theta
|
||
|
||
```
|
||
|
||
```py
|
||
5.0 0.927295218002
|
||
|
||
```
|
||
|
||
事实上,**Python**将返回的两个值变成了元组:
|
||
|
||
In [19]:
|
||
|
||
```py
|
||
print to_polar(3, 4)
|
||
|
||
```
|
||
|
||
```py
|
||
(5.0, 0.9272952180016122)
|
||
|
||
```
|
||
|
||
因为这个元组中有两个值,所以可以使用
|
||
|
||
```py
|
||
r, theta = to_polar(3, 4)
|
||
```
|
||
|
||
给两个值赋值。
|
||
|
||
列表也有相似的功能:
|
||
|
||
In [20]:
|
||
|
||
```py
|
||
a, b, c = [1, 2, 3]
|
||
print a, b, c
|
||
|
||
```
|
||
|
||
```py
|
||
1 2 3
|
||
|
||
```
|
||
|
||
事实上,不仅仅返回值可以用元组表示,也可以将参数用元组以这种方式传入:
|
||
|
||
In [21]:
|
||
|
||
```py
|
||
def add(x, y):
|
||
"""Add two numbers"""
|
||
a = x + y
|
||
return a
|
||
|
||
z = (2, 3)
|
||
print add(*z)
|
||
|
||
```
|
||
|
||
```py
|
||
5
|
||
|
||
```
|
||
|
||
这里的`*`必不可少。
|
||
|
||
事实上,还可以通过字典传入参数来执行函数:
|
||
|
||
In [22]:
|
||
|
||
```py
|
||
def add(x, y):
|
||
"""Add two numbers"""
|
||
a = x + y
|
||
return a
|
||
|
||
w = {'x': 2, 'y': 3}
|
||
print add(**w)
|
||
|
||
```
|
||
|
||
```py
|
||
5
|
||
|
||
```
|
||
|
||
## map 方法生成序列
|
||
|
||
可以通过 `map` 的方式利用函数来生成序列:
|
||
|
||
In [23]:
|
||
|
||
```py
|
||
def sqr(x):
|
||
return x ** 2
|
||
|
||
a = [2,3,4]
|
||
print map(sqr, a)
|
||
|
||
```
|
||
|
||
```py
|
||
[4, 9, 16]
|
||
|
||
```
|
||
|
||
其用法为:
|
||
|
||
```py
|
||
map(aFun, aSeq)
|
||
```
|
||
|
||
将函数 `aFun` 应用到序列 `aSeq` 上的每一个元素上,返回一个列表,不管这个序列原来是什么类型。
|
||
|
||
事实上,根据函数参数的多少,`map` 可以接受多组序列,将其对应的元素作为参数传入函数:
|
||
|
||
In [24]:
|
||
|
||
```py
|
||
def add(x, y):
|
||
return x + y
|
||
|
||
a = (2,3,4)
|
||
b = [10,5,3]
|
||
print map(add,a,b)
|
||
|
||
```
|
||
|
||
```py
|
||
[12, 8, 7]
|
||
|
||
``` |