找回密码
 会员注册
查看: 36|回复: 0

Python学习之——装饰器

[复制链接]

4

主题

0

回帖

13

积分

新手上路

积分
13
发表于 2024-9-7 13:35:10 | 显示全部楼层 |阅读模式
Python学习之——装饰器参考基础闭包概念装饰器系统自带的装饰器@property@staticmethod@classmethod自定义装饰器函数的装饰器无参数有参数类的装饰器无参数有参数@functools.wraps装饰器类装饰器实现单例模式参考python装饰器的4种类型:函数装饰函数、函数装饰类、类装饰函数、类装饰类9.4定义一个带参数的装饰器基础闭包概念Python闭包(Closure)详解闭包概念:在一个内部函数中,对外部作用域的变量进行引用,并且外部函数的返回值为内部函数,那么内部函数就叫做闭包。示例:defouter_func(year):definner_func(month):print(f'year:{year},month:{month}')returninner_funcclosure_func=outer_func('2023')closure_func(12)1234567'运行运行调用func时,产生了闭包inner_func,其持有外层函数的自由变量year,当函数func的生命周期结束之后,year这个变量依然存在,因为它被闭包引用了,不会被回收。闭包的特点:内部函数可以读取外层函数内的局部变量,并让其常驻内存,不会被回收,所以注意内存泄漏装饰器一文搞懂什么是Python装饰器装饰器是用来增强函数/类功能的一个函数importloggingdefno_arg_decorator(func):call_count=0definner_func(*arg,**kwargs):#dosomethings,examplenonlocalcall_countcall_count+=1print(f'call{func.__name__}func,totalcallcount:{call_count}')func(*arg,**kwargs)returninner_funcdefarg_decorator(*outer_arg,**outer_kwargs):definner_func(func):definner_func2(*arg,**kwargs):#dosomethingsuseouter_arg,outer_kwargs,examplefile_path=outer_kwargs.get('log_file_path')iffile_path:logging.basicConfig(filename=file_path,format='%(asctime)s-%(name)s-%(levelname)s-%(message)s-%(funcName)s',level=logging.DEBUG)logging.debug(f'debug,call{func.__name__},arg:{arg},kwargs:{kwargs}')func(*arg,**kwargs)returninner_func2returninner_funcdeftest_func1(a=1):pass#1.不用语法糖@符号​​​​​​​#1.1无参装饰器wraped_func1=no_arg_decorator(test_func1)#1.2有参装饰器wraped_func2=arg_decorator(log_file_path='log.txt')(test_func1)#2.采用语法糖@符号​​​​​​​#2.1无参装饰器@no_arg_decoratordeftest_func2(a=1):pass#2.2有参装饰器@arg_decorator(log_file_path='log.txt')deftest_func3(a=1):passif__name__=='__main__':print('=========================')wraped_func1()wraped_func1()wraped_func2(a=11)test_func2()test_func3(a=111)#结果=========================calltest_func1func,totalcallcount:1calltest_func1func,totalcallcount:2calltest_func2func,totalcallcount:112345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970系统自带的装饰器@propertyPython中property()函数及@property装饰器classFood(object): def__init__(self): self._price=0@propertydefprice(self):returnself._price@price.setterdefprice(self,value):ifvaluestr: """时间戳转utc-0时区的时间""" datetime_obj:datetime=datetime.utcfromtimestamp(timestamp) returndatetime_obj.strftime(format_str) @staticmethod deftimestamp_to_local_str(timestamp:float,format_str=TIME_FORMAT_STR)->str: """时间戳转当前本地时区的时间""" datetime_obj:datetime=datetime.fromtimestamp(timestamp) returndatetime_obj.strftime(format_str)123456789101112131415161718@classmethodclassmethod修饰过的方法叫类方法,可以直接通过类或者实例调用方法利用@classmethod实现单例模式fromdatetimeimportdatetimeclassSingletonBase(object):__instance=None@classmethoddefget_instance(cls,*arg,**kwargs):ifcls.__instanceisNone:cls.__instance=cls()cls.__instance.init(*arg,**kwargs)returncls.__instancedefinit(self,*arg,**kwargs):passclassTestMgr(SingletonBase):definit(self,*arg,**kwargs):print(f'IamTestMgrSingleton,arg:{arg},kwargs:{kwargs}')if__name__=='__main__': test_mgr=TestMgr.get_instance('hello','world',time=datetime.now().strftime("%Y/%m/%d/%H:%M:%S"))12345678910111213141516171819202122232425'运行运行自定义装饰器python装饰器2:类装饰器python装饰器的4种类型:函数装饰函数、函数装饰类、类装饰函数、类装饰类函数的装饰器无参数importtimeall_func={}#用于函数注册的装饰器defregister_func(func):all_func[func.__name__]=funcreturnfunc#用于统计函数耗时的装饰器defcalc_time(func):definner_func():start=time.time()func()end=time.time()print(f'call{func.__name__}func,costtime:{int(end-start)}second')returninner_func@calc_timedeftest_func4():time.sleep(2)if__name__=='__main__':print('=========================')test_func4()#结果=========================calltest_func4func,costtime:2second123456789101112131415161718192021222324252627282930313233有参数#-*-coding:utf-8-*-fromfunctoolsimportwrapstest_dict={}defDecorator(arg1=0,arg2=1):definner_func(func):funcName=func.__name__test_dict[funcName]=func#没有returnfunc,则该装饰器默认返回None,会导致被Decorator装饰后的函数无法被调用,#有returnfunc,则被Decorator装饰后的函数还是被赋值为原函数,后续还可以调用#returnfuncreturninner_funcdefdecorator(*arg):returnDecorator(*arg)defDecorator2(arg1=0,arg2=1):definner_func(func)wraps(func)defwrapper(*args,**kwargs):#dosomethingreturnfunc(*args,**kwargs)funcName=func.__name__test_dict[funcName]=func#有returnwrapper,则被Decorator2装饰后的函数还是被赋值为原函数,后续还可以调用returnwrapperreturninner_funcdefdecorator2(*arg):returnDecorator2(*arg)@Decorator()deftest_func_a():pass@decorator()deftest_func_b():pass@Decorator2()deftest_func_c():pass@decorator2()deftest_func_d():passif__name__=="__main__":print(test_dict)#结果{'test_func_a':,'test_func_b':,'test_func_c':,'test_func_d':}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263类的装饰器无参数#decorator1(cls)返回一个函数inner_func的写法defdecorator1(cls):definner_func(a):print('classname:',cls.__name__)returncls(a)returninner_func#decorator2(cls)返回一个类inner_cls的写法defdecorator2(cls):classinner_cls:def__init__(self,*args,**kwargs):self.wrapped_obj=cls(*args,**kwargs)def__getattr__(self,name):returngetattr(self.wrapped_obj,name)returninner_cls@decorator1classFooClass1():def__init__(self,a):self.a=adeffun(self):print('self.a=',self.a)@decorator2classFooClass2():def__init__(self,a):self.a=adeffun(self):print('self.a=',self.a)foo1=FooClass1('Foo1_a')foo1.fun()foo2=FooClass2('Foo2_a')foo2.fun()1234567891011121314151617181920212223242526272829303132333435363738394041'运行运行有参数1.通过装饰器实现子类的自动注册all_subcls={}defregister_subcls(base_cls_name):defdecorate(sub_cls):ifbase_cls_namenotinall_subcls:all_subcls[base_cls_name]={}all_subcls[base_cls_name][sub_cls.__name__]=sub_clsreturndecoratedefget_subcls(base_cls_name,sub_cls_name): ifbase_cls_namenotinall_subcls: returnNone else: returnall_subcls[base_cls_name].get(sub_cls_name)#使用classTestBase1(object): @staticmethod defcreate_instance(sub_cls_name,*args,**kwargs): sub_cls=get_subcls('TestBase1',sub_cls_name) returnsub_cls(*args,**kwargs)ifsub_clselseNone def__init__(self,*args,**kwargs): self.args=args self.kwargs=kwargs defprint_self(self): print(f'TestBase1,args:{args},kwargs:{kwargs}')@register_subcls('TestBase1')classTestA(TestBase1): defprint_self(self): print(f'TestA,args:{args},kwargs:{kwargs}')@register_subcls('TestBase1')classTestB(TestBase1): defprint_self(self): print(f'TestB,args:{args},kwargs:{kwargs}')123456789101112131415161718192021222324252627282930313233343536373839通过装饰器给类增加静态函数/类函数/成员函数#实例方法defadd_instance_method(cls):definner_func(func):setattr(cls,func.__name__,func)returninner_func#类方法defadd_class_method(cls):definner_func(func):setattr(cls,func.__name__,classmethod(func))returninner_func#静态方法defadd_static_method(cls):definner_func(func):setattr(cls,func.__name__,staticmethod(func))returninner_funcdefadd_func_decorator(cls)add_instance_method(cls)deftest_instance_func(self):print('test_instance_func')@add_class_method(cls)deftest_class_func(cls):print('test_class_func')@add_static_method(cls)deftest_static_func():print('test_static_func')returncls@add_func_decoratorclassTestClass():def__init__(self):passif__name__=='__main__':TestClass.test_class_func()TestClass.test_static_func()test_obj=TestClass()test_obj.test_instance_func()#结果test_class_functest_static_functest_instance_func123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354@functools.wrapsfunctools.wraps对我们的装饰器函数进行了装饰之后,消除了装饰器对原函数的影响。具体Python装饰器深度解析装饰器类之前都是用函数来构造装饰器,其实类也可以用来构建装饰器装饰器类先熟悉一下Python__call__()方法Python中,凡是可以将()直接应用到自身并执行,都称为可调用对象。可调用对象包括自定义的函数、Python内置函数以及本节所讲的类实例对象。__call__()方法的功能类似于在类中重载()运算符,使得类实例对象可以像调用普通函数那样,以“对象名()”的形式使用。fromfunctoolsimportwrapsclasslogit(object):def__init__(self,logfile='out.log'):self.logfile=logfiledef__call__(self,func)wraps(func)defwrapped_function(*args,**kwargs):log_string=func.__name__+"wascalled"print(log_string)withopen(self.logfile,'a')asfp:fp.write(log_string+'\n')#发送一个通知self.notify()returnfunc(*args,**kwargs)returnwrapped_functiondefnotify(self):pass#使用@logit()defmyfunc1():pass1234567891011121314151617181920212223242526'运行运行装饰器实现单例模式Python单例模式(Singleton)的N种实现1.使用函数装饰器实现单例defSingleton(cls):_instance={}definner():ifclsnotin_instance:_instance[cls]=cls()return_instance[cls]returninner@SingletonclassCls(object):def__init__(self):passcls1=Cls()cls2=Cls()print(id(cls1)==id(cls2))1234567891011121314151617'运行运行2.使用类装饰器实现单例classSingleton(object):def__init__(self,cls):self._cls=clsself._instance={}def__call__(self):ifself._clsnotinself._instance:self._instance[self._cls]=self._cls()returnself._instance[self._cls]@SingletonclassCls2(object):def__init__(self):passcls1=Cls2()cls2=Cls2()print(id(cls1)==id(cls2))#同时,由于是面对对象的,这里还可以这么用classCls3():passCls3=Singleton(Cls3)cls3=Cls3()cls4=Cls3()print(id(cls3)==id(cls4))12345678910111213141516171819202122232425262728'运行运行
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2025-1-10 22:45 , Processed in 0.429529 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表