广西建设工程质量安全监督总站网站,平台公司是什么,做外汇网站,怎么建设国外网站一、递归函数
1.1 基本信息
递归函数是指一个函数在其定义中直接或间接地调用了自身
递归在解决许多问题#xff08;如树的遍历、图的搜索、数学中的分治算法等#xff09;时非常有用
在Python中#xff0c;递归函数可以通过简单的语法来实现
然而#xff0c;使用递归…一、递归函数
1.1 基本信息
递归函数是指一个函数在其定义中直接或间接地调用了自身
递归在解决许多问题如树的遍历、图的搜索、数学中的分治算法等时非常有用
在Python中递归函数可以通过简单的语法来实现
然而使用递归时需要小心以避免导致无限递归栈溢出或性能低下的问题
1.2 递归函数使用条件
1、明确的结束条件 2、每进行更深一层的递归时问题规模相比上次递归都要有所减少 3、相邻两次重复之间有紧密的联系
eg1分别用普通函数和递归函数来实现计算1-100累加和
普通函数
def add():s 0for i in range(1,101):s iprint(s)
add ()
# 输出结果5050
递归函数
def add2(n): # 要累加到第n项# 如果是1就返回1 ---明确的结束条件if n 1:return 1# 如果不是1重复执行累加并返回结果return n add2(n-1)
print(add2(100))
# 输出结果5050
eg2斐波那契数列11235813...
规律从第三项开始每一项都等于前两项之和即 n n-2 n-1)
n当前项 n-1前一项 n-2前两项
def funa(n): # n代表第n项if n 1:return nreturn funa(n-2)funa(n-1)
print(funa(5))
# 输出结果5
1.3 递归函数的优缺点
优点简洁、逻辑清晰、解题更具有思路
缺点使用递归函数时需要反复调用函数耗内存运行效率低用循环容易解决的问题首选循环
二、闭包
2.1 含义使用条件
含义:在嵌套函数的前提下内部函数使用了外部函数的变量而且外部函数返回了内部函数我们就把使用了外部函数变量的内部函数称为闭包
在Python中闭包Closure是指一个函数对象它记住了其创建时的环境即外部作用域中的变量。即使这个函数对象被传递到其他地方调用它仍然可以访问这些外部变量。闭包的一个常见用途是创建带有私有变量的函数工厂或数据封装
使用前提条件
1、嵌套函数闭包通常涉及嵌套函数即在一个函数内部定义另一个函数
2、非局部变量内部函数可以访问外部函数的局部变量这些变量在外部函数返回后通常会被销毁但由于闭包的存在它们被保留了下来
3、返回内部函数外部函数返回内部函数对象这个返回的函数对象就是闭包
eg1
def outer(): # 外层函数n 10 # 外层函数的局部变量def inner(): # 内层函数print(n) # 内层函数使用外层函数的局部变量# 外层函数的返回值是内层函数的函数名return inner
# print(outer()) # 返回的是内部函数的内存地址# 第一种调用写法
outer()() # 输出结果10# 第二种调用写法
ot outer() # 调用外函数
ot() # 调用内函数
# 输出结果10
eg2
def outer(m): # 外函数m是形参也是外函数的局部变量n 10def inner(): # 内函数print(计算结果,mn)return inner # 返回函数名而不是inner(),因为inner函数里面参数比较多时或者说受限制时写法不太规范
ot outer(20) # 调用外函数
ot() # 调用内函数
# 输出结果计算结果 30
2.2 函数引用
eg1
def funa():print(123)
print(funa) # 输出内容function funa at 0x00000265916D6948 函数名里面保存了函数所在位置的引用
# id():判断两个变量是否是同一个值的引用
a 1 # a只不过是一个变量名存的是1这个数值所在的地址就是a里面存了数值1的引用
print(a) # 1
print(id(a)) # 输出内容140720708025408
a 2 # 修改a生成了新的值重新赋值给变量a
print(id(a)) # 输出内容140720708025440
eg2
def test1(): # test1也只不过是一个函数名里面存了这个函数所在位置的引用print(这是test函数)
test1()
print(test1) # 内存地址引用
te test1
te() # 通过引用调用函数
每次开启内函数都在使用同一份闭包变量
eg:
def outer(m):print(outer()函数中的值:,m)def inner(n):print(inner()函数中的值:,n)return mn #在inner函数中返回mtn的值return inner
otouter(10)#调用外的数给outer()传值
# print(ot)
# 第一次调用内函数给inner()函数传值
print(ot(20)) # 调用内函数给inner()传值 1020
# 输出结果
# outer()函数中的值: 10
# inner()函数中的值: 20
# 30
# 第二次调用内函数
print(ot(40)) # 1040
# 第三次调用内函数
print(ot(80)) # 1080
总结:使用闭包的过程中一旦外函数被调用一次返回了内函数的引用虽然每次调用内函数会开启一个函数执行后消亡但是闭包变量实际上只有一份每次开启内函数都在使用同一份闭包变量
三、装饰器
3.1 装饰器基础
在 Python 中装饰器decorator是一种用于修改或扩展函数或方法行为的高级功能。它们本质上是一个闭包函数它接受一个函数作为参数并返回一个新的函数。装饰器使用语法糖来应用
装饰器非常有用特别是当你需要在不修改原有函数代码的情况下为其添加额外的功能如日志记录、性能计时、权限检查等时
3.1.1 标准版装饰器
装饰器的原理就是将原有的函数名重新定义为以原函数为参数的闭包
eg
# 被装饰的函数
def send():print(发送消息)# 装饰器函数
def outer(fn): # 外层函数fn是形参但是往里面传入的是被装饰的函数名send# 既包含原有功能又包含新功能def inner(): # 内函数print(登录...)# 执行被装饰的函数fn() # send()return inner
print(outer(send)) # function outer.locals.inner at 0x0000024D4FE069D8
ot outer(send) # 调用外函数
ot() # 调用内函数 3.1.2 语法糖
Python提供了一种简洁的语法糖syntactic sugar来定义和使用装饰器即使用符号
格式装饰器名称
eg:
def outer(fn):def inner():print(登录...)# 执行被装饰的函数fn()return inner
# 注意装饰器名称后面不要加上()且语法糖最好紧挨着被修饰函数
outer
def send():print(发送消息笑死我了)
send()outer
def send2():print(发送消息哈哈哈)
send2()
# 输出结果
# 登录...
# 发送消息笑死我了
# 登录...
# 发送消息哈哈哈
eg一个简单的装饰器示例它用于计算函数的执行时间
import time def timing_decorator(func): def wrapper(*args, **kwargs): start_time time.time() result func(*args, **kwargs) end_time time.time() elapsed_time end_time - start_time print(fFunction {func.__name__} executed in {elapsed_time:.4f} seconds) return result return wrapper timing_decorator
def some_function(seconds): print(fSleeping for {seconds} seconds...) time.sleep(seconds) print(Done sleeping!) # 使用装饰器
some_function(2)
在这个例子中
timing_decorator 是一个装饰器函数它接受一个函数 func 作为参数
wrapper 是装饰器内部定义的函数它包裹了 func并添加了计时功能
*args 和 **kwargs 允许 wrapper 函数接受任意数量和类型的参数并将它们传递给 func
在 wrapper 函数中我们首先记录开始时间然后调用 func 并保存其结果
接着我们记录结束时间计算并打印函数执行的时间
最后wrapper 函数返回 func 的结果
通过使用 timing_decorator 语法我们轻松地将 timing_decorator 应用于 some_function无需修改 some_function 的代码
3.2 带有参数的装饰器
装饰器本身也可以接受参数
eg1标准版带参
def outer(fn): # 外层函数fn是形参但是往里面传入的是被装饰的函数名funcdef inner(name): # 内函数name是内函数的参数print(f{name}是inner函数中的参数)print(哈哈哈哈)fn(name)return inner
def func(name):print(这是被修饰的函数)ot outer(func) # ot inner
ot(junjun) # 调用内函数# 输出结果
# junjun是inner函数中的参数
# 哈哈哈哈
# 这是被修饰的函数
eg2语法糖带参
def outer(fn): # 外层函数fn是形参但是往里面传入的是被装饰的函数名funcdef inner(name): # 内函数name是内函数的参数print(f{name}是inner函数中的参数)print(哈哈哈哈)fn(name)return inner
outer
def func(name):print(这是被修饰的函数)
func(junjun)
# 输出结果
# junjun是inner函数中的参数
# 哈哈哈哈
# 这是被修饰的函数
为了实现这一点可以使用嵌套函数被装饰函数为可变参数*args、**kwargs
def repeat_decorator(num_times): def decorator_func(func): def wrapper(*args, **kwargs): for _ in range(num_times): result func(*args, **kwargs) return result return wrapper return decorator_func repeat_decorator(3)
def greet(name): print(fHello, {name}!) # 使用装饰器
greet(Alice)
在这个例子中repeat_decorator 接受一个参数 num_times并返回一个真正的装饰器函数 decorator_func。decorator_func 接受一个函数 func 并返回包裹 func 的 wrapper 函数
3.3 多个装饰器
多个装饰器的装饰过程离函数最近的装饰器先装饰然后外面的装饰器再进行装饰由内到外的装饰过程
egdeco1在前deco2在后
# 第一个装饰器
def deco1(fn):def inner():return 哈哈哈fn()呵呵呵return inner
# 第二个装饰器
def deco2(fn):def inner():return 奈斯fn()非常优秀return inner# 被装饰的函数
deco1
deco2
def test1():return 晚上在学习Python基础
print(test1())
# 输出结果哈哈哈奈斯晚上在学习Python基础非常优秀呵呵呵
# 多个装饰器的装饰过程离函数最近的装饰器先装饰然后外面的装饰器再进行装饰由内到外的装饰过程 deco2在前deco1在后
# 第一个装饰器
def deco1(fn):def inner():return 哈哈哈fn()呵呵呵return inner
# 第二个装饰器
def deco2(fn):def inner():return 奈斯fn()非常优秀return inner# 被装饰的函数
deco2
deco1
def test1():return 晚上在学习Python基础
print(test1())
# 输出结果奈斯哈哈哈晚上在学习Python基础呵呵呵非常优秀
# 多个装饰器的装饰过程离函数最近的装饰器先装饰然后外面的装饰器再进行装饰由内到外的装饰过程
3.4 保留函数元数据
在装饰器内部定义的 wrapper 函数通常会覆盖被装饰函数的元数据如 __name__ 和 __doc__
为了保留这些元数据可以使用 functools.wraps 装饰器
eg:
from functools import wraps def my_decorator(func): wraps(func) def wrapper(*args, **kwargs): print(fCalling {func.__name__}) result func(*args, **kwargs) print(f{func.__name__} returned {result}) return result return wrapper my_decorator
def add(a, b): Return the sum of a and b. return a b print(add.__name__) # 输出: add
print(add.__doc__) # 输出: Return the sum of a and b.
functools.wraps 装饰器确保了 wrapper 函数保留了 func 的名称和文档字符串等元数据
今天的分享就到这里了希望能帮助到大家~