【Python基础学习篇八】Python函数

函数是一段可以重复多次调用的代码,通过输入的参数值,返回需要的结果。

一、函数的定义

函数的定义使用保留字def定义。函数在使用前必须定义,函数的类型即返回值的类型。

Python函数定义的格式如下:

def 函数名 (参数1[=默认值1],参数2[=默认值2]...):
    ...
return 表达式

函数名可以是字母、数字或下划线组成的字符串,但不能以数字开头。函数的参数放在一对圆括号中,参数的个数可以有一个或多个,参数之间用逗号隔开,这种参数称之为形式参数。

例子:

#!/usr/bin/env python
# -*- coding=utf-8 -*-
#Using GPL v2.7
#Author: [email protected]
#函数的定义
from __future__ import division
def arithmetic(x,y,operator):
    result = {
        "+":x + y,
        "-":x - y,
        "*":x * y,
        "/":x / y
    }

arithmetic()已经创建成功,剩下的就是函数的调用的问题了。函数可以在当前文件中调用,也可以在其他模块中调用。

函数调用的格式如下所示:

函数名(实参1,实参2...)

函数的调用采用函数名加一对圆括号的方式,圆括号内的参数是传递给函数的具体值。函数调用中的实参列表分别与函数定义中的形参列表对应。

下图说明了实际参数和形式参数的对应关系。

1

arichmetic()的调用如下所示:

#函数的调用
print arithmetic(1,2,"+")

注意:

实际参数必须与形式参数一一对应,参数的顺序和参数的类型必须一致,否则将出现错误计算。如果参数提供默认值,顺序可以不一致。

二、函数的参数

在Python中的任何变量都是对象,所以参数只支持引用传递的方式。Python通过名字绑定的机制,把实际参数的值和形式参数的名称绑定在一起。即把形式参数传递到函数所在的局部命名空间中,形式参数和实际参数指向内存中的同一个存储空间。

函数的参数支持默认值。当某个参数没有传递实际的值时,函数将使用默认参数计算。

例如可以给arichmetic()参数都提供一个默认值。

#!/usr/bin/env python
# -*- coding=utf-8 -*-
#Using GPL v2.7
#Author: [email protected]
def arithmetic(x = 1,y = 1,operator = "+"):
    result = {
        "+":x + y,
        "-":x - y,
        "*":x * y,
        "/":x / y
    }
    return result.get(operator)

print arithmetic(1,2)
print arithmetic(1,2,"=")
print arithmetic(y=3,operator = "-")
print arithmetic(x=4,operator = "-")
print arithmetic(y=3,x=4,operator = "-")

输出结果:

---------- python2.7 ----------
3
None
-2
3
1

输出完成 (耗时 0 秒) - 正常终止

参数可以是变量,也可以是元组、列表等内置数据结构:

#!/usr/bin/env python
# -*- coding=utf-8 -*-
#Using GPL v2.7
#Author: [email protected]
def arithmetic(args = [],operator = "+"):
    x = args[0]
    y = args[1]
    result = {
        "+":x + y,
        "-":x - y,
        "*":x * y,
        "/":x / y
    }

print arithmetic([1,2])

输出结果:

---------- python2.7 ----------
None

输出完成 (耗时 0 秒) - 正常终止

由于参数实现了名字绑定的机制,所以在使用默认参数时,可能会出现预期之外的结果:

#!/usr/bin/env python
# -*- coding=utf-8 -*-
#Using GPL v2.7
#Author: [email protected]
def append(args = []):
    args.append(0)
    print args

append()
append([1])
append()

输出结果:

---------- python2.7 ----------
[0]
[1,0]
[0,0]

输出完成 (耗时 0 秒) - 正常终止

为了避免这个问题,可以在append()中添加一个条件判断语句。如果列表中args中没有任何元素,则先把args列表置空,谈后再添加元素:

#!/usr/bin/env python
# -*- coding=utf-8 -*-
#Using GPL v2.7
#Author: [email protected]
def append(args = []):
    if len(args) <=0:
        args = []
    args.append(0)
    print args

append()
append([1])
append()

输出结果:

---------- python2.7 ----------
[0]
[1, 0]
[0]

输出完成 (耗时 0 秒) - 正常终止

在程序的开发过程中,常常需要传递可变长度的参数。在函数的参数前使用标识符“*”可以实现这个要求。“*”可以引用元组,把多个参数组合到一个元组中。

#!/usr/bin/env python
# -*- coding=utf-8 -*-
#Using GPL v2.7
#Author: [email protected]
def func(* args):
    print args
func(1,2,3)

输出结果:

---------- python2.7 ----------
(1, 2, 3)

输出完成 (耗时 0 秒) - 正常终止

三、函数的返回值

函数的返回值使用return语句,return后面可以是变量或表达式。

例子:

#!/usr/bin/env python
# -*- coding=utf-8 -*-
#Using GPL v2.7
#Author: [email protected]
from __future__ import division
def arithmetic(x,y,operator):
    result = {
        "+":x + y,
        "-":x - y,
        "*":x * y,
        "/":x / y
    }
    return result.get(operator)

Python中即使函数没有返回值,依然可以获得返回值。

例子:

#!/usr/bin/env python
# -*- coding=utf-8 -*-
#Using GPL v2.7
#Author: [email protected]
def func():
    pass

print func()

输出结果:

---------- python2.7 ----------
None

输出完成 (耗时 0 秒) - 正常终止

None是Python中的一个对象,不属于数字也不属于字符串。当函数中的return语句不带任何参数时,返回的结果也是None

例子:

#!/usr/bin/env python
# -*- coding=utf-8 -*-
#Using GPL v2.7
#Author: [email protected]
def func():
    return

print func()

输出结果:

---------- python2.7 ----------
None

输出完成 (耗时 0 秒) - 正常终止

如果需要返回多个值,可以把这些值打包到元组中。在调用时,对返回的原则解包即可。

例子:输入0、1、2,返回2、1、0

#!/usr/bin/env python
# -*- coding=utf-8 -*-
#Using GPL v2.7
#Author: [email protected]
def func(x,y,z):
    l = [x,y,z]
    l.reverse()
    numbers = tuple[1]
    return numbers

x,y,z = func(0,1,2)
print x,y,z

第二种解决方法:

#!/usr/bin/env python
# -*- coding=utf-8 -*-
#Using GPL v2.7
#Author: [email protected]
def func(x,y,z):
    l = [x,y,z]
    l.reverse()
    a,b,c = tuple[1]
    return a,b,c

x,y,z = func(0,1,2)
print x,y,z

在一个函数中也可以使用多个return语句。

例如if…else语句的各个分支最后那个,返回不同的结果:

#!/usr/bin/env python
# -*- coding=utf-8 -*-
#Using GPL v2.7
#Author: [email protected]
def func(x):
    if x > 0:
        return "x > 0"
    elif x == 0:
        return "x = 0"
    else:
        return "x < 0"
print func(-2)

输出结果:

---------- python2.7 ----------
x < 0

输出完成 (耗时 0 秒) - 正常终止

注意:

不推荐在一个函数中使用富哦个return语句,return语句过多往往会造成程序的复杂,这时就需要对代码进行重构了。

如果函数中有多个return语句,可以通过增加一个变量的方法来减少return语句:

#!/usr/bin/env python
# -*- coding=utf-8 -*-
#Using GPL v2.7
#Author: [email protected]
def func(x):
    if x > 0:
        result = "x > 0"
    elif x == 0:
        result = "x = 0"
    else:
        result = "x < 0"
    return result
print func(-2)

输出结果:

---------- python2.7 ----------
x < 0

输出完成 (耗时 0 秒) - 正常终止

四、函数的嵌套

函数的嵌套是指在函数的内部调用其他函数。Python不仅支持函数体内的嵌套,还支持函数定义的嵌套。

例如:

计算表达式(x+y)*(m-n)的值。

可以把计算步骤分为3步:先计算表达式x+y,其次计算表达式m-n,最后计算两个结果的乘积。

因此,可以设计3个函数。

第一个函数sum()计算x+y的值;

第二个函数sub()计算m-n的值;

第三个函数计算前面两者的乘积。

1

例子:函数之间的调用操作

#!/usr/bin/env python
# -*- coding=utf-8 -*-
#Using GPL v2.7
#Author: [email protected]
def sum(a,b):
    return a + b
def sub(a,b):
    return a - b
def func():
    x = 1
    y = 2
    m = 3
    n = 4
    return sum(x,y)*sub(m,n)
print func()

输出结果:

---------- python2.7 ----------
-3

输出完成 (耗时 0 秒) - 正常终止

注意:

函数嵌套的层数不宜过多,否则容易造成代码的可读性差、不易维护等问题。一般函数的嵌套调用控制在3层以内为好。

上面的代码可以换一种形式实现,即把函数sum()、sub()放到func()的内部,如下图所示:

1

例子:

#!/usr/bin/env python
# -*- coding=utf-8 -*-
#Using GPL v2.7
#Author: [email protected]
def func():
    x = 1
    y = 2
    m = 3
    n = 4
    def sum(a,b):
        return a + b
    def sub(a,b):
        return a - b
    return sum(x,y)*sub(m,n)

print func()

输出结果:

---------- python2.7 ----------
-3

输出完成 (耗时 0 秒) - 正常终止

内部函数sum()、sub()也可以直接使用外部函数func()定义的变量,如下图:

1

例子:

#!/usr/bin/env python
# -*- coding=utf-8 -*-
#Using GPL v2.7
#Author: [email protected]
def func():
    x = 1
    y = 2
    m = 3
    n = 4
    def sum():
        return x + y
    def sub():
        return m - n
    return sum()*sub()

print func()

输出结果:

---------- python2.7 ----------
-3

输出完成 (耗时 0 秒) - 正常终止

说明:

尽量不要在函数内部定义函数。这种方式不便于程序的维护,容易造成逻辑上的混乱。

五、递归函数

递归函数可以在函数主题内直接或者间接地调用自己,即函数的嵌套是函数本身。递归四一种程序设计方法,使用递归可以减少重复的代码,使得程序变得简洁。

递归的过程分为两个阶段:递推和回归。

递归函数的原理如下:

第一阶段,递归函数在内部调用自己。每一次函数调用又重新开始执行此函数的代码,直到某一级递归程序结束。

第二阶段,递归函数从后往前返回。递归函数从最后一级开始返回,直到返回到第一次调用的函数体内。即递归逐级调用完毕后,再按照相反的顺序逐级返回。

特别说明:

递归函数需要编写递归结束的条件,否则递归程序将无法结束。一般通过判断语句来结束程序。

计算阶乘是一个经典的递归实现。

例如,计算5!的结果。在设计程序时,可以根据n是否等于1进行判断。每次递归调用,传入参数n-1.直到n=1时,返回1!等于1.再依次返回2!、3!、4!、5!的计算结果。如下图所示:

1

例子:用递归函数实现阶乘的计算过程

#!/usr/bin/env python
# -*- coding=utf-8 -*-
#Using GPL v2.7
#Author: [email protected]
#计算阶乘
def refunc(n):
    i = 1
    if n > 1:
        i = n
        n = n * refunc(n - 1)
    print "%d! =" %i,n
    return n

refunc(5)

输出结果:

---------- python2.7 ----------
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120

输出完成 (耗时 0 秒) - 正常终止

特别注意:

每次调用递归函数都会复制函数中所有的变量,再执行递归函数。程序需要较多的存储空间,这对程序的性能会有一定的影响。因此,对于没有必要进行递归的程序,最好用其他的方法进行改进。

可以使用reduce()快速实现阶乘的运算:

#!/usr/bin/env python
# -*- coding=utf-8 -*-
#Using GPL v2.7
#Author: [email protected]
#计算reduce阶乘
print "5! =",reduce(lambda x,y:x * y,range(1,6))

输出结果:

---------- python2.7 ----------
5! = 120

输出完成 (耗时 0 秒) - 正常终止

六、lambda函数

lambda函数用于创建一个匿名函数,函数名未和标识符进行绑定。使用lambda函数可以返回一些简单的运算结果。

lambda函数的格式如下所示:

lambda 变量1,变量2...:表达式

其中,变量列表用于表达式的计算。lambda属于函数,因此变量列表后需要一个冒号。通常把lambda赋值给一个变量,变量就可以作为函数使用。

例如:

#赋值
func = lambda 变量1,变量2...:表达式
#调用
func()

这样就把lambda和变量func绑定在一起了,变量func的名字就是函数名。

例子:使用lambda函数来计算(x + y)*(m - n)

#!/usr/bin/env python
# -*- coding=utf-8 -*-
#Using GPL v2.7
#Author: [email protected]

def func():
    x = 1
    y = 2
    m = 3
    n = 4
    sum = lambda x,y:x + y
    print sum
    sub = lambda m,n:m - n
    print sub
    return sum(x,y) * sub (m,n)

print func()

输出结果:

---------- python2.7 ----------
<function <lambda> at 0x00000000022529E8>
<function <lambda> at 0x0000000002252A58>
-3

输出完成 (耗时 0 秒) - 正常终止

注意:

lambda也称之为表达式。lambda中只能使用表达式,不能使用判断、循环等多重语句。

例子:把lambda赋值给一个变量使用,也可以把lambda直接作为函数使用:

#!/usr/bin/env python
# -*- coding=utf-8 -*-
#Using GPL v2.7
#Author: [email protected]
#lambda的函数用法
print(lambda x:-x)(-2)

输出结果:

---------- python2.7 ----------
2

输出完成 (耗时 0 秒) - 正常终止

说明:

定义匿名函数lambda x:-x,用于返回数字的绝对值。

 

七、generator函数

生成器(generator)的作用是一次产生一个数据项,并把数据项输出。genera函数可以用在for循环中遍历。generator函数所具有的每次返回一个数据项的功能,使得迭代器的性能更佳。

generator函数的定义如下所示:

def 函数名(参数列表):
    ...
    yield 表达式

generator函数的定义和普通函数的定义没什么区别,只要在函数体内使用yield生成数据项即可。

generator函数可以被for循环遍历,而且可以通过next()方法获得yield生成的数据项。

例子:

#!/usr/bin/env python
# -*- coding=utf-8 -*-
#Using GPL v2.7
#Author: [email protected]
#定义generator函数
def func(n):
    for i in range(n):
        yield i
#在for循环中输出
for i in func(3):
    print i
#使用next()输出
r = func(3)
print r.next()
print r.next()
print r.next()
print r.next()

输出结果:

---------- python2.7 ----------
0
1
2
0
1
2
Traceback (most recent call last):
  File "Noname1.py", line 17, in <module>
    print r.next()
StopIteration

输出完成 (耗时 0 秒) - 正常终止

说明:

参数n表示一个数字,该函数依次生成0到n个数字。

最后一次调用r.next(),由于n的值等于3,因此生成3个数字后,已经没有数据可生成。Python解释器抛出异常StopIteration

特别说明:

yield保留字与return语句的返回值和执行原理都不相同。yield生成值并不会终止程序的执行,返回值后程序继续往后执行。return返回值后,程序将中止执行。

例子:yield和return语句的区别。

#!/usr/bin/env python
# -*- coding=utf-8 -*-
#Using GPL v2.7
#Author: [email protected]
#yield与return区别
def func(n):
    for i in range(n):
        return i #直接返回i的值,循环语句将终止,整个程序到此结束
def func2(n):
    for i in range(n):
        yield i #循环生成n个数字,循环语句不会被终止

print func(3)
f = func2(3) #yield并没有返回任何值,而是返回了函数func2()的地址
print f
print f.next()
print f.next()

输出结果:

---------- python2.7 ----------
0
<generator object func2 at 0x000000000215A6C0>
0
1

输出完成 (耗时 0 秒) - 正常终止

generator函数可以返回元素的值,而序列也可以获取元素的值。但是两者还是存在很大的区别。generator函数依次只返回一个数据项,占用更少的内存。每次生成数据都要记录当前的状态,便于下一次生成数据。数据的访问时通过next()方法实现的。当访问越界时,generator函数会抛出异常StopIteration。序列一次返回所有的数据,元素的访问时通过索引完成的。当访问越界时,序列提示list index out of range错误。

当程序需要较高的性能或一次只需要一个值进行处理时,使用generator函数。当需要获取一次性一组元素的值时,使用序列。

你可能感兴趣的:(python)