一、递归
函数和方法的调用很多时候发生在不同的函数和方法之间,比如定义了def func_a函数与def func_b函数,在func_b函数中调用func_a,当然还存在一个特殊调用,即函数内部调用自身,这种调用方式就叫作递归调用,好处是大大减少代码量,把复杂问题简单化
计算一个阶乘如10!(s = 12345….*10)
递推方式实现
def iterative(n):
num = 1
for i in range(1,n+1):
#num *= i
num = num * i
return num
以1为基数通过for循环来实现阶乘计算,注意一个这个range(1,n+1 )前包含后不包含,所以取n+1
递归方法实现
def recursive(n):
if n <=1 :
return n
else:
return n * recursive(n-1)
递归缺点:运行速度慢于递推,内存消耗比较大
# 1,1,2,3,5,8,13,21,34,55,试判断数列第十五个数是哪个?
def fabonacci(n):
''' n为斐波那契数列 '''
if n <= 2:
''' 数列前两个数都是1 '''
v = 1
return v # 返回结果,并结束函数
v = fabonacci(n-1)+fabonacci(n-2) # 由数据的规律可知,第三个数的结果都是前两个数之和,所以进行递归叠加
return v # 返回结果,并结束函数
print(fabonacci(15)) # 610 调用函数并打印结果
非递归写法
# 斐波那契数列
def fib(n):
a, b = 1, 1
for i in range(n-1):
a, b = b, a+b
return a
当n=5即fib(5)
print("a","b")
for i in range(5-1):
a, b = b, a+b
print(a, b)
结果:
a b
1 2
2 3
3 5
5 8
二、装饰器
前提概念一:
闭包:在函数中再嵌套一个函数,并且引用外部函数的变量,这就是一个闭包了
def outer(x):
def inner(y):
return x + y
return inner
print(outer(6)(5))
函数中可定义函数
def func_1():
print("正在调用func_1")
def func_1_1():
return "正在调用func_1_1"
def func_1_2():
return "正在调用func_1_2"
print(func_1_1())
print(func_1_2())
print("函数func_1调用结束")
#
正在调用func_1
正在调用func_1_1
正在调用func_1_2
函数func_1调用结束
函数中定义的函数,只能在func_1函数内调用
前提概念二:
函数中返回函数
def func_1():
print("正在调用func_1")
def func_1_1():
return "正在调用func_1_1"
print("函数func_1调用结束")
return func_1_1
a = func_1() #正在调用func_1
函数func_1调用结束
print(a) # <function func_1.<locals>.func_1_1 at 0x000001B92BE3DAF0>
print(a()) # 正在调用func_1_1
问题:为什么 print(a) 与 print(a( ))不一样?
前提概念三:
赋值与调用
def func_2():
print("函数func_2被调用")
a = func_2
print(a) # <function func_2 at 0x00000219AAD8F040>
b = func_2() # 函数func_2被调用
c = a() # 函数func_2被调用
从上述代码可知,当 a = func_2 时,是把func_2函数对象内存地址赋值给变量a,并不会执行func_2这个函数中的代码;当 b = func_2( )时,函数func_2( )会被调用,加上()会运行这个函数中的代码
装饰器:
在Python中,可以把函数A作为参数传入另一个函数B,从而实现在不改变函数A原有代码的基础上对函数A增加新功能
def func_A():
print("A函数本身的功能")
def func_B(func):
print("执行func_B开始")
def func_b():
print("func_b执行传入函数前做一些事情")
func()
print("func_b执行传入函数后做一些事情")
print("准备返回func_b")
return func_b
b = func_B(func_A) # func_B()执行返回一个 func_b 内嵌函数对象给func_A调用
'''
执行func_B开始
准备返回func_b
func_b执行传入函数前做一些事情
A函数本身的功能
func_b执行传入函数后做一些事情
'''
上述代码func_B函数就是一个装饰器函数,但需要调用func_B函数来实现对func_A函数的功能拓展,
通过@符号装饰func_A函数,可实现直接调用func_A函数来达成装饰器的目的
@func_B
def func_A():
print("A函数本身的功能")
func_A()
'''
执行结果:
执行func_B开始
准备返回func_b
func_b执行传入函数前做一些事情
A函数本身的功能
func_b执行传入函数后做一些事情
'''
被装饰的A函数有单个参数
def func_B(func):
def func_b(x):
return 2*func(x)
return func_b
@func_B
def func_A(x):
return int(x)+1
if __name__ == "__main__":
a = func_A(2)
print(a)
print(func_A.__name__) # 结果为func_b,即func_A被装饰后指向了func_b
被装饰的A函数有多个参数
def func_B(func):
def func_b(*args,**kwargs):
return 2*func(*args,**kwargs)
return func_b
@func_B
def func_A(x,y):
return int(x)+int(y)
if __name__ == "__main__":
a = func_A(2,3)
print(a)