python-三器 装饰器(闭包)
我们知道对于一个普通的类,我们要使用其中的函数的话,需要对类进行实例化,而一个类中,某个函数前面加上了staticmethod或者classmethod的话,那么这个函数就可以不通过实例化直接调用
""" @staticmethod不需要表示自身对象的self和自身类的cls参数。如果在@staticmethod中要调用到这个类的一些属性方法,直接类名.属性名或类名.方法名。 @classmethod也不需要self参数,但第一个参数需要是表示自身类的cls参数。而@classmethod因为持有cls参数,可以来调用类的属性,类的方法,实例化对象等,避免硬编码。 @property使方法像属性一样调用,就像是一种特殊的属性。有参函数时使用@name.setter @pysnooper日志打印工具,用显示函数间的入参和返回值的变化 output='a.txt' #将结果保存到文件a.txt
variables=('a') #打印非局部变量a的值
depth=1 #Show snoop lines for functions that your function calls
prefix='hello' #在每一行打印信息前添加hello """ class Animal(object): name = 'dog' def __init__(self,name): self.name = name def intro1(self): print('there is a %s'%(self.name)) @staticmethod def intro2(): print('there is a %s') @staticmethod def intro3(test): print('there is a %s'%(test)) @classmethod def intro4(cls): #不传参 cls.intro1(cls) #调用类方法 print('there is a %s'%(cls.name)) @classmethod def intro5(cls,test): #传参 cls.intro1(cls) #调用类方法 print('there is a %s %s'%(cls.name,test)) @property def intro6(self): print('there is a %s eating'%(self.name)) @intro6.setter def intro7(self,value): print('there is %d %s eating'%(value,self.name)) import pysnooper @pysnooper.snoop() #@pysnooper.snoop('log.log') def lisy(a): return [x - 10 if x in [11, 12, 13] else x for x in a] if __name__ == '__main__': a = Animal('cat') a.intro1() Animal.intro2() Animal.intro3('test') Animal.intro4() Animal.intro5('test') a.intro6 a.intro7=2 lisy([1, 2, 3, 11, 12, 13, '111', 222])
装饰器分类
""" 1.修饰无参函数 2.修饰有参函数 3.不带参数的装饰器 4.带参数的装饰器 5.类装饰器 """ #修饰无参函数 #(无参数时不需要直接调用,在@log1时已经调用了) def log1(func): func() @log1 def test(): print('testlog1:',test.__name__) #修饰有参函数、无参数 def log2(func): def inner(*args, **kwargs): func(*args, **kwargs) return inner @log2 def test(num): print('testlog2:',num,test.__name__) test(20) #修饰有参函数(返回入参出参) def log3(func): def inner(*args, **kwargs): print('入参:',func.__name__, args, kwargs) res =func(*args, **kwargs) print('出参:',func.__name__, res) return res return inner @log3 def test(num): print('testlog3:', num, test.__name__) return num test(30) from functools import wraps #@wraps可以保证装饰器修饰的函数的name的值保持不变 #不带参数的装饰器 def log4(func): @wraps(func) def inner(*args, **kwargs,): func(*args, **kwargs) return inner @log4 def test(num): print('testlog4:',num,test.__name__) test(40) #带参数的装饰器 def log5(level): def log(func): @wraps(func) def inner(*args, **kwargs,): if level == "warn": print("%s is running" % func.__name__) func(*args, **kwargs) return inner return log @log5(level="warn") def test(num): print('testlog5:', num, test.__name__) test(50) #实现带参数和不带参数的装饰器自适应 def log6(arg): if callable(arg): # 判断入参的参数是否有值,不带参数的装饰器调用这个分支 def log4(func): @wraps(func) def inner(*args, **kwargs, ): func(*args, **kwargs) return inner return log4 else: def log5(func): @wraps(func) def inner(*args, **kwargs,): if arg == "warn": print("%s is running" % func.__name__) func(*args, **kwargs) return inner return log5 @log6(arg=None) def test(num): print('testlog:', num, test.__name__) test(0) #类装饰器 class Loging: def __init__(self, level): self.level = level def __call__(self, func): @wraps(func) def inner(*args, **kwargs): if self.level == "warn": print("%s is running" % func.__name__) func(*args, **kwargs) return inner @Loging(level="warn") def test(num): print('testLoging:', num, test.__name__) test(0) class LogClass: def __init__(self, func): self.func = func def __call__(self, *args, **kwargs): print('初始化装饰器') self.func(*args, **kwargs) print('中止装饰器') @LogClass def test(num): print('testLogClass:', num) test(0)
装饰器应用
def log(func): def inner(*args, **kwargs): try: func(*args, **kwargs) except Exception as e: print(e) print('截图') finally: print('清除test函数') return inner @log def test(): raise Exception("抛出一个异常") test()
def fixedFuncOnce(func): """ 修饰函数(固定函数只执行一次)-有返回 @param func: @return: """ cache = {} @wraps(func) def inner(*args,**kwargs): key = func.__name__ #函数的名称作为key result = None if key in cache.keys(): result = cache[key] #key不存在 if result is None: result = func(*args, **kwargs) cache[key] = result return result return inner def fixedTimeOnce(func): """ 修饰函数(固定时间只执行一次)-有返回 @param func: @return: """ cache = {} @wraps(func) def inner(*args,**kwargs): key = func.__name__ #函数的名称作为key result = None if key in cache.keys(): (tmp,updateTime) = cache[key] if time.time() -updateTime < 5: result=tmp #key不存在、或者过期 if result is None: result = func(*args, **kwargs) cache[key] = (result, time.time()) return result return inner def sameParameterOnce(func): """ 修饰函数(相同参数值只执行一次)-有参数 @param func: 目标函数 @return: """ savefunc = {} @wraps(func) def inner(*args, **kwargs): key = func.__name__ result = None if key in savefunc.keys(): ss = savefunc[key] f = lambda x: x.get("args") == args and x.get("kwargs") == kwargs if list(filter(f,ss)): #判断函数参数 result = ss[0]["result"] else: #或者参数不一样 result = func(*args, **kwargs) savefunc[key].append({"args": args, "kwargs": kwargs, "result": result}) else: #key不存 result = func(*args, **kwargs) savefunc[key] = [{"args": args,"kwargs": kwargs,"result": result}] return result return inner
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
2020-04-13 Mysql查询字段与关键字重名