如何理解使用Python的装饰器
首先Python的装饰器值是一种语法糖,用于动态修改函数或类的行为
大白话就是Python的装饰器只是Python语法指令的简单写法,他是用来修饰类和函数实现一些辅助功能,不使用装饰器也可以,可能实现起来比较麻烦(优雅是Python追求的特点之一)!
Python装饰器的基本原理:一个函数可以接受另一个函数作为参数,然后返回一个新的函数一个引例deflog(func):defwrapper(args,kw):print(calls():func。name)returnfunc(args,kw)returnwrapperlogdefmyfunc(args,kw):print(helloworld)
在这个例子中定义了一个装饰器log,它接受一个函数作为参数,然后返回一个新的函数wrapper。wrapper函数中输出了一段日志,并调用原来的函数func。
我们用log语法将装饰器应用到了myfunc函数上,相当于执行了如下语句:myfunclog(myfunc)
这样,再用myfunc()函数时,log函数把myfunc()函数的参数打包给了wrapper()函数,wrapper()函数在执行之前会对myfunc()函数进行一些装饰!然后再执行myfunc()函数。
那么问题来了?为什么会执行wrapper()函数呢,我们仅仅是定义了它,并没有调用,看到log函数结束时的返回语句:returnwrapper就是对wrapper的调用,那这样顺序就里清楚了
当然你也可以选择不用装饰器,实现相同的效果,那样程序就得改成这样:deflog(func,args,kw):print(calls():func。name)returnfunc(args,kw)defmyfunc(args,kw):print(helloworld)log(myfunc)
这样你每次运行myfunc函数的时候外面就得套个log函数,而且当myfunc函数有参数时,你还得把参数传递给log,就显得调用起来十分麻烦!装饰器的精髓就是装饰器函数把它需要修饰函数的参数一同打包传递给了内部定义的函数,并且执行内部定义的函数装饰器的其它应用计时装饰器:记录函数执行时间。缓存装饰器:将函数的返回值缓存起来,避免重复计算。权限验证装饰器:检查用户是否有访问某个页面的权限。日志记录装饰器:记录函数的执行结果或异常信息
一个计时装饰器的例子importtimedeftimer(func):defwrapper(args,kwargs):starttimetime。time()resultfunc(args,kwargs)endtimetime。time()print(f函数{func。name}执行时间:{endtimestarttime})returnresultreturnwrappertimerdefmyfunc(n):time。sleep(n)myfunc(2)输出:函数myfunc执行时间:2。0025088787078857
这个不必多说,和上面log()装饰是一个道理,你可以尝试不用装饰器实现上面的功能!
在这个例子中,定义了一个计时装饰器timer,它会在函数执行前记录开始时间,执行后记录结束时间,并输出函数执行时间。然后,我们用timer将它应用到了myfunc函数上,这样每次执行myfunc(n)函数时,都会输出函数执行时间Python中一些特定的装饰器
1、property:用于将一个方法转化为只读属性。可以让我们在不改变原有代码的情况下,对类的外部接口进行改进classMyClass:definit(self,x):self。xxpropertydefx(self):returnself。xcMyClass(10)print(c。x)输出:10
在这个例子中,定义了一个类MyClass,其中包含一个私有属性x,和一个方法x,并用property装饰器将方法转化为只读属性。这样,在外部访问c。x时,实际上是调用了c。x()方法
2、staticmethod:用于将一个方法转化为静态方法。静态方法可以直接通过类名调用,不需要实例化对象classMyClass:staticmethoddeff(x,y):returnxyprint(MyClass。f(10,20))输出:30
在这个例子中,我们定义了一个类MyClass,其中包含一个静态方法f,并用staticmethod装饰器将其转化为静态方法。这样,在外部调用MyClass。f时,不需要实例化MyClass对象。
3、classmethod:用于将一个方法转化为类方法。类方法的第一个参数是类对象,可以通过它访问类的属性和方法。classMyClass:x10classmethoddeff(cls):returncls。xprint(MyClass。f())输出:10
在这个例子中,我们定义了一个类MyClass,其中包含一个类属性x,和一个类方法f,并用classmethod装饰器将其转化为类方法。这样,在类方法中可以通过第一个参数cls访问类属性x
4、functools。wraps:用于修饰装饰器。如果我们定义一个装饰器,它会修改被装饰函数的行为,但是在外部调用被装饰函数时,函数的名称和文档字符串会发生改变。为了保留原有的名称和文档字符串,可以使用functools。wraps装饰器。importfunctoolsdefmydecorator(func):functools。wraps(func)defwrapper(args,kwargs):print(Callingdecoratedfunction)returnfunc(args,kwargs)returnwrappermydecoratordefexample():Docstringprint(Calledexamplefunction)print(example。name)输出:exampleprint(example。doc)输出:Docstring
如果对Python编程感兴趣,可以私聊小编!
编程Python