一、函数的参数
1. 默认参数
函数的默认参数有以下要求:
-
必选参数在前,默认参数在后 (例1)
-
当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。可以只传入变化大的参数,变化小的参数就可以作为默认参数(例2)
-
当函数有多个参数时,可以单独调用函数时指定某个参数(例2)
-
默认参数必须指向不变对象(例3)
# 例1 def pow(x, n=2): s = 1 while n > 0: n -= 1 s *= x return s print(pow(5,3)) #125 print(pow(5)) #25 # 例2 def addStudents(name,age=18,sex="保密"): print(f"姓名= {name},年龄 = {age},性别 = {sex}") addStudents("张甲") # 姓名= 张甲,年龄 = 18,性别 = 保密 addStudents("张甲",22) #姓名= 张甲,年龄 = 22,性别 = 保密 addStudents("张甲",sex="男") #姓名= 张甲,年龄 = 18,性别 = 男 # 例3 def add_end(L=[],M=None): L.append('END') if M is None: M = [] M.append("END") return L,M print(add_end()) #(['END'], ['END']) print(add_end()) # (['END', 'END'], ['END'])
2. 可变参数
可变参数只需要在参数前添加一个*即可,在函数内部,参数接收到的是一个tuple
def total(*num): sum = 0 for i in num: sum += i return sum print(total()) #0 print(total(1,2,3)) #6 nums = [1,2,3,4] print(total(*nums)) #传入list,结果为10
3. 关键字参数
在函数内部,参数接收到的是一个dict,该dict是对参数的一份拷贝,对参数的改动不会影响到函数外的参数值。
def persion(**kw): kw['sex'] = '保密' print(kw) persion(city='RiZhao', age=20) # {'city': 'RiZhao', 'age': 20} per = {'name': 'ZhangJia', 'sex': '男'} persion(**per) #{'name': 'ZhangJia', 'sex': '保密'} print(per) # {'name': 'ZhangJia', 'sex': '男'} 不会影响per的值
4. 命名关键字参数
如果要限制关键字参数的名字,可以用命名关键字参数
-
命名关键字参数需要一个特殊分隔符*,*后面的参数被视为命名关键字参数
-
命名关键字参数必须传入参数名(例1)
-
如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了 (例2)
-
命名关键字参数可以有缺省值,从而简化调用(例3)
#例1 def person(name, age, *, city, job): print(name, age, city, job) person("ZhangJia",18,"日照","银行工作者") #报错 person("ZhangJia",18) #报错 person("ZhangJia",18,city="日照",job = "银行工作者") #ZhangJia 18 日照 银行工作者 #例2 def person(name, age, *args, city, job): print(name, age, city, job) #person("ZhangJia",18,"日照","银行工作者") #报错 #person("ZhangJia",18) person("ZhangJia",18,city="日照",job = "银行工作者") #ZhangJia 18 日照 银行工作者 #例3 def person(name, age, *, city="日照", job): print(name, age, city, job) person("ZhangJia",18,job = "银行工作者") #ZhangJia 18 日照 银行工作者
5. 参数组合
在Python中定义函数时,必选参数、默认参数、可变参数、命名关键字参数、关键字参数这5种参数可以组合使用。
-
参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。
-
对于任意函数,都可以通过类似func(*args, **kw)的形式调用它,无论它的参数是如何定义的,*args表示任何多个无名参数,它是一个tuple;**kwargs表示关键字参数,它是一个dict。同时使用*args和**kwargs时,必须*args参数列要在**kwargs前
6. 练习
定义一个函数可接收一个或多个数并计算乘积:
#方法1 def mul(*x): if len(x) == 0: raise TypeError y = 1 for i in x: y *= i return y #方法2 def mul(x,*y): for i in y: x *= i return x
二、递归函数
一个函数在内部调用自身本身,这个函数就是递归函数。
练习:计算阶乘n! = 1 x 2 x 3 x … x n,用函数fact(n)表示,fact(n)可以表示为n x fact(n-1),n=1时,返回1
def fact(n): if n == 1: return 1 return n * fact(n - 1)
值得注意的是,使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。
解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。
尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。
请登录之后再进行评论