Python的函数
Python定义函数
除了使用Python内置的函数以外,在编程过程中,我们也经常需要自己定义函数。
在Python中,定义一个函数要使用 def 语句,依次写出函数名、括号()、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用 return 语句返回。
我们以定义一个求绝对值的函数my_abs函数为例:
def my_abs(x): if x >= 0: return x else: return -x
请注意,return表示返回的意思,函数体内部的语句在执行时,一旦执行到return时,函数就执行完毕,并将结果返回。因此,函数内部通过条件判断和循环可以实现非常复杂的逻辑。
我们继续定义一个求列表list所有元素的和的函数:
def list_sum(L): 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中每个元素平方的和。
def square_of_sum(L): for item in L: index_num = L.index(item) print "item ",item print "index_num ",index_num L[index_num] = item*item return L print(square_of_sum([1,3,6,9,12,54]))
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! = 1 * 2 * 3 * ... * (n-1) * n = (n-1)! * n = fact(n-1) * n
所以,fact(n)可以表示为 n * fact(n-1),只有n=1时需要特殊处理。
于是,fact(n)用递归的方式写出来就是:
def fact(n): if n==1: return 1 return n * fact(n - 1)
这个fact(n)就是递归函数,可以试试计算得到的结果。
fact(1) # ==> 1 fact(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)。
Traceback (most recent call last): RecursionError: maximum recursion depth exceeded in comparison
请分别使用循环和递归的形式定义函数,求出1~100的和。
def fact(n): if n==1: return 1 return n+fact(n-1) print(fact(500))
Python函数使用默认参数
定义函数的时候,还可以有默认参数,默认参数的意思是当这个参数没有传递的时候,参数就使用定义时的默认值。
例如Python自带的 int() 函数,其实就有两个参数,我们既可以传一个参数,又可以传两个参数:
int('123') # ==> 123 int('123', 8) # ==> 83
int()函数的第二个参数是转换进制base,如果不传,默认是十进制 (base=10),如果传了,就用传入的参数。
可见,函数的默认参数的作用是简化调用,你只需要把必须的参数传进去。但是在需要的时候,又可以传入额外的参数来覆盖默认参数值。
我们来定义一个计算 x 的N次方的函数:
def power(x, n): s = 1 while n > 0: n = n - 1 s = s * x return s
假设计算平方的次数最多,我们就可以把 n 的默认值设定为 2:
def power(x, n=2): s = 1 while n > 0: n = n - 1 s = s * x return s
这样一来,计算平方就不需要传入两个参数了:
power(5) # ==> 25
另外需要注意的是,由于函数的参数按从左到右的顺序匹配,所以默认参数只能定义在必需参数的后面,否则将会出现错误。
# 错误的定义 def power(n=2, x): s = 1 while n > 0: n = n - 1 s = s * x return s
请定义一个 greet() 函数,它包含一个默认参数,如果没有传入参数,打印 Hello, world.
,如果传入参数,打印Hello, 传入的参数内容.
#incoding:utf-8 def greet(n='', s="你好!"): if n.strip() == '': return s else: return n,s print(greet("111"))
Python函数使用可变参数
除了默认参数,Python函数还接收一种参数叫做可变参数,可变参数即任意个参数的意思,可变参数通常使用*args
来表示。
def func(*args): print('args length = {}, args = {}'.format(len(args), args)) func('a') # ==> args length = 1, args = ('a',) func('a', 'b') # ==> args length = 2, args = ('a', 'b') func('a', 'b', 'c') # ==> args length = 3, args = ('a', 'b', 'c')
注意,在使用上,Python会把可变参数定义为一个tuple,所以在函数内部,把可变参数当作tuple来使用就可以了,比如可以通过位置下标取出对应的元素等。
定义可变参数的目的也是为了简化调用。假设我们要计算任意个数的平均值,就可以定义一个可变参数:
def average(*args): sum = 0 for item in args: sum += item avg = sum / len(args) return avg
这样,在调用的时候,我们就可以这样写:
average(1, 2) # ==> 1.5 average(1, 2, 2, 3, 4) # ==> 2.4 average() # 报错 Traceback (most recent call last): ZeroDivisionError: division by zero
在执行average()
的时候,却报错了,这是因为在使用可变参数时,没有考虑周全导致的,因为可变参数的长度可能是0,当长度为0的时候,就会出现除0错误。因此需要添加保护的逻辑,这是同学在使用过程中需要特别注意的。
请完善average()函数,使得当可变参数长度为0的时候,也能正确返回结果
def average(*args): sum = 0 if len(args)==0: return num for item in args: sum += item avg = sum / len(args) return avg print(average(5,5,5,5,5))
原文:https://www.imooc.com/learn/1261