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

posted @ 2021-05-18 12:20  sucre_tan  阅读(283)  评论(0编辑  收藏  举报