python 函数

来源:互联网 发布:恋爱循环知乎 编辑:程序博客网 时间:2024/05/16 09:46

空函数

如果想定义一个什么事也不做的空函数,可以用pass 语句,当然pass 也可以做为占位符。

def nop(age):    if age >= 18:        pass

参数

参数检查

调用函数时,python解释器会自动检查参数个数;但不会检查参数类型。因此,需要在函数内部对参数类型做检查(可利用内置函数isinstance

def my_abs(x):    if not isinstance(x, (int, float)):        raise TypeError('bad operand type')    if x >= 0:        return x    else:        return -x

默认参数

在设置默认参数时,有几点必须要注意:
1、必选参数在前,默认参数在后。否则 python的解释器会报错
2、设置默认参数。当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数

有个很有意思的例子:

def add_end(L=[]):    L.append('END')    return L>>> add_end()>['END']>>> add_end()>['END','END']

原因在于:
在python中,默认参数L为一个变量,指向对象list[]。每次调用该函数时,如果改变了list 的内容,而默认参数会指向该对象,也就意味着默认参数的内容变了。
因此,定义默认参数要牢记一点:默认参数必须指向不变对象!

可变参数

在python函数中,可以定义可变参数(传入的参数个数是可变的)

def calc(*number):    sum = 0    for n in numbers:        sum += n * n    return sum

可变参数是仅仅在参数前面加了一个* 号。在函数内部,参数numbers 接收到的是一个元组,因此函数代码完全不变。但是,调用函数时,可以传入任意个参数,包括0个参数:
如果此时有一个list或者tuple要调用一个可变函数,需要在list或tuple前面加一个* 号,把list或tuple的元素变成可变参数传进去:

>>> nums = [1,2,3]>>> calc(*nums)>14

关键字参数

可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装成一个tuple。而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装成一个dict。关键字参数是在参数前面加一个** 号。

参数组合

参数定义的顺序必须为:必选参数、默认参数、可变参数和关键字参数

递归函数

递归函数在内部调用自身本身。其优点是定义简单,逻辑清晰。但使用递归函数需要注意防止 栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧。每当函数返回,栈就会减一层栈帧。所以,递归调用的次数过多会导致栈溢出。
解决递归调用栈溢出的方法是通过尾递归优化。尾递归是指在函数返回时调用自身本身,并且return语句不能包含表达式。顾名思义,尾递归就是从最后开始计算,每递归一次就算出相应的结果,也就是说,函数调用出现在调用者函数的尾部,因为是尾部,所以根本没有必要去保存任何局部变量,直接让被调用的函数返回时越过调用者。尾递归就是把当前的运算结果或路径放在参数里传递给下一层函数

def fact(n):    if n == 1:        return 1    return n * fact(n-1)"""    尾递归优化"""def fact(n):    return fact_iter(n, 1)def fact_iter(num, product):    if num == 1:        return product    return fact_iter(num - 1, product * num)

尾递归函数的出现是为了解决递归调用栈溢出的问题。如果,编译器或者解释器将尾递归进行优化,使递归本身无论调用多少次都只占用一个栈帧,就不会出现栈溢出的情况。
但可笑的是,大多数编程语言都没有针对尾递归做优化。当然,python解释器也没有做优化。

0 0
原创粉丝点击