python基础之 装饰器,内置函数
1.闭包回顾
在学习装饰器之前,可以先复习一下什么是闭包?
在嵌套函数内部的函数可以使用外部变量(非全局变量)叫做闭包!
def wrapper(): money =10 def inner(num): nonlocal money money +=num print(money) print(inner.__closure__) #不返回none的话就是闭包 return inner wrapper()(100)
装饰器的本质就是闭包
2.装饰器
装饰器本质上就是一个python函数,他可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象。
装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等场景。
#简单的装饰器 def func(): print('嘻嘻更健康') def timmer(f): def inner(): start_time = time.time() time.sleep(0.1) f() end_time = time.time() print('----> 执行效率%s' % (end_time - start_time)) return inner func = timmer(func) # inner func() # inner()
这是最简单的装饰器,装饰任何函数,只需要加一句func = timmer(func)
3.装饰器语法糖
import time def timer(func): def inner(): start = time.time() func() print(time.time() - start) return inner @timer 等价于func1 = timer(func1),@timer会先拿到下面函数的名字,然后把拿到名字的函数传给timer装饰器函数 def func1(): print('in func1') func1()

def timer(func): def inner(a): start = time.time() func(a) print(time.time() - start) return inner @timer def func1(a): print(a) func1(1)

import time def timer(func): def inner(*args,**kwargs): start = time.time() re = func(*args,**kwargs) print(time.time() - start) return re return inner @timer #==> func1 = timer(func1) def func1(a,b): print('in func1') @timer #==> func2 = timer(func2) def func2(a): print('in func2 and get a:%s'%(a)) return 'fun2 over' func1('aaaaaa','bbbbbb') print(func2('aaaaaa'))
上面的装饰器已经非常完美了,但是有我们正常情况下查看函数信息的方法在此处都会失效:
from functools import wraps def deco(func): @wraps(func) #加在最内层函数正上方,显示被装饰的函数 def wrapper(*args,**kwargs): return func(*args,**kwargs) return wrapper @deco def index(): '''哈哈哈哈''' print('from index') print(index.__doc__) #显示被装饰函数的注释 print(index.__name__) #显示被装饰的函数名
4.开放封闭原则
开放对扩展代码--->新添加的功能 封闭修改源代码--->不要修改源代码 改变了人家调用方式---->不能改变其原有的调用方式
5.带参数的装饰器
假如你有成千上万个函数使用了一个装饰器,现在你想把这些装饰器都取消掉,你要怎么做? 一个一个的取消掉? 没日没夜忙活3天。。。 过两天你领导想通了,再让你加上。。。 def outer(flag): def timer(func): def inner(*args,**kwargs): if flag: print('''执行函数之前要做的''') re = func(*args,**kwargs) if flag: print('''执行函数之后要做的''') return re return inner return timer @outer(False) def func(): print(111) func()
6.多个装饰器装饰一个函数
def wrapper1(func): def inner(): print('wrapper1 ,before func') func() print('wrapper1 ,after func') print('wrapper1.inner',id(inner)) return inner def wrapper2(func): def inner(): print('wrapper2 ,before func') func() print('func',id(func)) print('wrapper2 ,after func') print('wrapper2.inner',id(inner)) return inner @wrapper2 # wrapper1.inner = wrapper2(wrapper1.inner) == wrapper2.inner @wrapper1 # f = wrapper1(f)===>f =wrapper1.inner def f(): print('in f') f() print(id(f)) #装饰器是函数最上面的装饰器开始调用,但是执行是从上面的装饰器开始执行的 #嵌套装饰器的返回值,返回给上一层 wrapper2 ,before func wrapper1 ,before func in f wrapper1 ,after func wrapper1.inner 189913016 func 189913016 wrapper2 ,after func wrapper2.inner 189913560 189913560
多层嵌套装饰器的返回值(函数对象),返回给上一层,意义是:给装饰器在加上一个装饰器
7.装饰器执行流程及原理,作用
装饰器的组成:
1.闭包 2.语法糖
装饰器的作用:
1.装饰器本质上是一个高级Python函数,通过给别的函数添加@标识的形式实现对函数的装饰
2.它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。
装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。
装饰器的原理:就是利用闭包函数来实现,闭包函数的原理就是包含内层函数的return和外层环境变量
8.高级内置函数
***#高级函数默认已经帮我们做了一次for循环的过程**** lambda: 是匿名函数,不需要定义,直接调用,可以配合其他高级函数一起使用 lambda x:x>3 第一个是参数,第二个是返回值(可以做filter的过滤条件) sorted: 排序,sorted([1,3,4,2,7,6]) 默认是升序排序,加上reverse=True是降序, sorted(li,key=func)可以有两个参数,第一个参数必须是可迭代对象,第二个参数key是指定的排序规则,可以是函数,也可以是表达式 sorted配合lambda li =['你好啦啦啦啦','我很好','大家都好'] print(sorted(li,key=lambda x:len(x))) filter: 是过滤函数,filter(func,li),第一个参数是一个函数的内存地址,第二个参数是可迭代对象,和sorted正好相反 filter配合lambda li = [1,3,6,2,5,4,8,11,23,45,14] #排除小于5的并排序 print(sorted(filter(lambda x:x>5,li)))# 既然是过滤函数,就得有过滤条件,正好lambda的第二个参数是返回值,就可以以其为过滤条件 map/reduce map: map(func,li)函数接收两个参数,一个是函数,一个是Iterable, map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。 map映射函数, 这里面的map(lambda x:x*x,ls) ,第一个lambda x:x*x是map的第一个参数函数内存地址,第二个ls是可迭代对象,和filter是一样的位置传参数li111 = [1,2,3,4] map应用 1.将li111 = [1,2,3,4]快速转成str print(list(map(str,li111))) #将int快速转成str 2. ls= [1,2,3,4,5] print(list(map(lambda x:x*x,ls))) reduce:(感觉有点像递归函数)
reduce把一个函数作用在一个序列[x1, x2, x3, ...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算 第一个参数是函数的内存地址,第二个参数是可迭代对象第一个参数是函数的内存地址,第二个参数是可迭代对象 他调用的方法中必须要两个参数,第一个参数一直使用return出来的值,第二个参数是循环可迭代对选对象的元素 from functools import reduce li111 = [1,2,3,4] def func23(x,y): return x*10 +y print(reduce(func23,li111))
zip:函数是python代码中非常常用的一个操作。
其以可迭代对象为输入参数,将可迭代对象里元素分别取出再组合成一个个元组,返回一个列表。
a = ['name', 'age', 'sex']
b = ['alex', 35, 'Male']
print(dict(zip(a,b)))
什么情况需要加list()函数转化一下?
map()传入的第一个参数是f,即函数对象本身。由于结果r是一个Iterator,Iterator是惰性序列,因此通过list()函数让它把整个序列都计算出来并返回一个list。
9.内置函数
https://docs.python.org/zh-cn/3.7/library/functions.html
文章:https://www.cnblogs.com/eric_yi/p/7255455.html
文章:https://www.cnblogs.com/cicaday/p/python-decorator.html
文章:https://yiyibooks.cn/xx/python_352/library/index.html
上帝说要有光,于是便有了光;上帝说要有女人,于是便有了女人!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类