Python的函数
- 9. Python的函数一
- 9.1 什么是函数
- 9.2 Python定义函数
- 9.3 Python函数返回值
- 9.4 Python递归函数
9. Python的函数一
9.1 什么是函数
我们把封装重复逻辑代码的过程就做抽象,抽象是数学中非常常见的概念. 借助抽象,我们才能不关心底层的具体计算过程,而直接在更高的层次上思考问题. 写计算机程序也是一样,函数就是最基本的一种代码抽象的方式.
Python不但能非常灵活地定义函数,而且本身内置了很多有用的函数, 可以直接调用.
- Python调用函数
Python内置了很多有用的函数,我们可以直接调用。比如前面求list的长度len()函数等等,都是Python内置的函数,我们经常会使用到它们。
在这个文档里面,列举了Python内置的大部分函数,同学们有兴趣可以参考看看。
https://docs.python.org/3/library/functions.html
要调用一个函数,需要知道函数的名称和参数,比如求绝对值的函数 abs(),它接收一个参数。
对于abs()函数,abs就是函数的名称,括号()内,就是函数的参数,当函数没有参数时,默认就是一个空括号。abs接收一个参数,这个参数就是需要求绝对值的数,这个参数可以是整数,也可以是浮点数
abs(20) # ==> 20
abs(-3.14159) # ==> 3.14159
需要注意的是,传递的参数数量一定要和函数要求的一致,不然将会引起错误,比如,如果在abs()函数中传入两个参数。
abs(1, 2)# 报错
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: abs() takes exactly one argument (2 given)
在错误提示中,清晰的说明了abs()函数只接收一个参数,但是却传递了两个参数,所以引起了错误。
其次,如果传入的参数数量是对的,但是参数的类型不能被函数所接受,也会引起错误,比如:求绝对值的函数abs(),只有数字才拥有绝对值,如果传递一个字符串进去,将会引起错误。
# 报错
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: bad operand type for abs(): 'str'
这里错误提示说,str类型是错误的参数类型。
除了abs()函数,还有很多常见的函数,比如cmp()函数,可以比较两个数的大小,这个时候,cmp()函数就接收两个参数。
对于cmp(x, y),如果x < y 返回 -1,如果x == y 函数返回0,如果x > y函数返回1
cmp(2, 1) # ==> 1
cmp(3, 3) # ==> 0
还有基础数据类型的转换函数,int()函数可以将合法的其它类型数据转换为整数,str()函数可以将其它类型的数据转换为字符串。
int('123') # ==> 123int(12.34) # ==> 12
str(123) # ==> '123'
str(1.23) # ==> '1.23'
在学习Python的过程中,我们将会接触到越来越多的Python内置函数,这些内置函数提供了非常有用的功能,大大降低我们编程的难度
示例
sum()函数接收一个list作为参数,并返回list所有元素之和。请计算 1*1 + 2*2 + 3*3 + ... + 100*100# Enter a codeL = []
x = 1
while x <= 100:
L.append(x * x)
x = x + 1
print(sum(L))
9.2 Python定义函数
除了使用Python内置的函数以外,在编程过程中,我们也经常需要自己定义函数
在Python中,定义一个函数要使用 def 语句,依次写出函数名、括号()、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用 return 语句返回
我们以定义一个求绝对值的函数my_abs函数为例:
if x >= 0:
return x
else:
return -x
请注意,return表示返回的意思,函数体内部的语句在执行时,一旦执行到return时,函数就执行完毕,并将结果返回。因此,函数内部通过条件判断和循环可以实现非常复杂的逻辑。
我们继续定义一个求列表list所有元素的和的函数:
result = 0
for num in L:
result = result + num
return result
这样子我们就定义了一个sum_list()的函数,注意,在最后return,我们把求和的结果result返回了,这样就可以在外部调用函数后获得result
L = [1, 3, 5, 7, 9, 11]result =list_sum(L) # 调用定义的sum_list函数并获得return返回的结果
print(result)
示例
请定义一个square_of_sum()函数,它接收一个list,返回list中每个元素平方的和
# Enter a codedef square_of_sum(L):
sum = 0
for x in L:
sum = sum + x * x
return sum
print(square_of_sum([1, 2, 3, 4, 5]))
print(square_of_sum([-5, 0, 5, 15, 25]))
9.3 Python函数返回值
有时候函数是没有返回结果的,这个时候从函数获取到的是一个空值None。
我们对list_sum()这个函数进行简单的修改,在函数内把结果打印出来,不通过return返回结果。
result = 0
for num in l:
result = result + num
print('result is {}'.format(result))
return
l = [1, 3, 5, 7, 9, 11]
result =list_sum(l) # 调用定义的sum_list函数并获得return返回的结果
print(result) # ==> None
在print(result)中,我们得到None的结果,这是合理的,因为在函数内部,我们把结果打印出来了,但是没有把结果返回
除了返回None、一个值以外,函数也可以返回多个值,在函数中,如果需要返回多个值,多个值之间使用逗号分隔即可,但是需要注意顺序。
比如,定义一个函数data_of_square,接收边长一个参数,同时返回正方形的周长和面积
C = 4 * side
S = side * side
return C, S
C, S = data_of_square(16)
print('周长 = {}'.format(C)) # ==> 周长 = 64
print('面积 = {}'.format(S)) # ==> 面积 = 256
也可以使用一个值存储函数返回的多值结果
result = data_of_square(16)print(result) # ==> (64, 256)
注意打印的result,其实它是tuple类型,如果我们需要取出结果中的周长或者面积,使用对应位置的下标就可以获得对应的结果
result = data_of_square(16)C = result[0]
S = result[1]
print('周长 = {}'.format(C)) # ==> 周长 = 64
print('面积 = {}'.format(S)) # ==> 面积 = 256
示例
定义一个函数sub_sum(),这个函数接收一个列表作为参数,函数返回列表所有奇数项的和以及所有偶数项的和
# coding=utf-8def sub_sum(L):
index = 0
sum1 = 0
sum2 = 0
for item in L:
if index % 2 == 0:
sum1 += item
else:
sum2 += item
index += 1
return sum1, sum2
L = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
result = sub_sum(L)
print('奇数项的和 = {}'.format(result[0]))
print('偶数项的和 = {}'.format(result[1]))
9.4 Python递归函数
在函数内部,还可以调用其他函数,比如实现函数data_of_square的时候,它接收边长一个参数,同时返回正方形的周长和面积,而求周长和求面积是完全独立的逻辑,可以定义成两个新的函数,然后在data_of_square函数中再调用这两个函数,得到结果并返回
def square_area(side):return side * side
def square_perimeter(side):
return 4 * side
def data_of_square(side):
C = square_perimeter(side)
S = square_area(side)
return C, S
在函数内部调用其他函数,是非常常见的,通过合理拆分逻辑,可以降低程序的复杂度。如果在一个函数内部调用其自身,这个函数就是递归函数
举个例子,我们来计算阶乘 n! = 1 * 2 * 3 * … * n,用函数 fact(n)表示,可以看出:
所以,fact(n)可以表示为 n * fact(n-1),只有n=1时需要特殊处理。
于是,fact(n)用递归的方式写出来就是:
if n==1:
return 1
return n * fact(n - 1)
这个fact(n)就是递归函数,可以试试计算得到的结果。
fact(1) # ==> 1fact(5) # ==> 120
我们可以拆解fact(5)计算的详细逻辑
===> fact(5)===> 5 * fact(4)
===> 5 * (4 * fact(3))
===> 5 * (4 * (3 * fact(2)))
===> 5 * (4 * (3 * (2 * fact(1))))
===> 5 * (4 * (3 * (2 * 1)))
===> 5 * (4 * (3 * 2))
===> 5 * (4 * 6)
===> 5 * 24
===> 120
递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。
使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。可以试试计算 fact(10000)
RecursionError: maximum recursion depth exceeded in comparison
示例
请分别使用循环和递归的形式定义函数,求出1~100的和
# coding=utf-8# 循环
def my_sumA(n):
sum = 0
index = 1
while index <= n:
sum += index
index += 1
return sum
# 递归
def my_sumB(n):
sum = 0
if n == 1:
sum = n
else:
sum = n + my_sumB(n - 1)
return sum