其实,python 中的装饰器本质上就是一个函数,这个函数接收其他的函数作为参数,并将其以一个全新的修改后的函数替换它
关于装饰器的知识是python面试中比较常见的,对于装饰器的理解可以看这篇文章:理解Python中的装饰器,理解之后,再手写一遍下面的8种装饰器加深理解以后使用就更轻松多了!1.最简单的函数
def myfunc()
print "i am a function"
myfunc()
2.初步了解装饰函数的调用结构
在函数执行前和执行后分别计时,打印函数运行消耗的时间
import datetime
import time
def out(fun):
start = datetime.datetime.now()
fun()
end = datetime.datetime.now()
print (end-start)
return fun
def inner():
time.sleep(1)
print ("i am inner func")
myfunc = out
myfunc(inner)
3.尝试引用@语法糖来调用装饰函数
import datetime,time
def out(func):
start =datetime.datetime.now()
func()
end = datetime.datetime.now()
print(end-start)
return func
@out
def myfunc():
time.sleep(1)
print("zhangkun inner")
4.使用内嵌的包装函数
使用内嵌包装函数来确保每次新函数都被调用,内嵌包装函数的形参和返回值与原函数相同,装饰函数返回内嵌包装函数对象
import datetime,time
def out(func):
def inner():
start = datetime.datetime.now()
func()
end = datetime.datetime.now()
print(end-start)
print("out and inner")
return inner
@out
def myfunc():
time.sleep(1)
print("zhangkun")
myfunc()
5.对带参数的函数使用装饰器
内嵌包装函数的形参和返回值与原函数相同,装饰函数返回内嵌包装函数对象
import datetime,time
def out(func):
def inner(*args):
start = datetime.datetime.now()
func(*args)
end = datetime.datetime.now()
print(end-start)
print("out and inner")
return inner
@out
def myfunc(*args):
time.sleep(1)
print("args is{}".format(args))
myfunc("lalalal")
6.给装饰器参数
和上一示例相比在外层多了一层包装
#coding:utf-8
def outermost(*args):
def out(func):
print ("装饰器参数{}".format(args))
def inner(*args):
print("innet start")
func(*args)
print ("inner end")
return inner
return out
@outermost(666)
def myfun(*args):
print ("试试装饰器和函数都带参数的情况,被装饰的函数参数{}".format(args))
myfun("zhangkun")
7.带类参数的装饰器
class locker:
def __init__(self):
print("locker.__init__() should be not called")
@staticmethod
def acquire():
print("locker.acquire() static method be called")
@staticmethod
def release():
print("locker.release() static method be called")
def outermost(cls):
def out(func):
def inner():
cls.acquire()
func()
cls.release()
return inner
return out
@outermost(locker)
def myfunc():
print("myfunc called")
myfunc()
8.对一个函数应用多个装饰器
class mylocker:
def __init__(self):
print("mylocker.__init__() called.")
@staticmethod
def acquire():
print("mylocker.acquire() called.")
@staticmethod
def unlock():
print(" mylocker.unlock() called.")
class lockerex(mylocker):
@staticmethod
def acquire():
print("lockerex.acquire() called.")
@staticmethod
def unlock():
print(" lockerex.unlock() called.")
def lockhelper(cls):
def _deco(func):
def __deco2(*args, **kwargs):
print("before %s called." % func.__name__)
cls.acquire()
try:
return func(*args, **kwargs)
finally:
cls.unlock()
return __deco2
return _deco
class example:
@lockhelper(mylocker)
@lockhelper(lockerex)
def myfunc2(self, a, b):
print(" myfunc2() called.")
print(a+b)
a = example()
a.myfunc2(1,2)
9.作为一个类
虽然装饰器几乎总是可以用函数实现,但是在某些情况下,使用用户自定义的类可能会更好,如果装饰器需要复杂的参数化或者依赖特定状态,那么这种说法往往是对的
非参数化装饰器用作类的通用模式如下
class DerocatorAsClass:
def __init__(self,funcation):
self.funcation = funcation
def __call__(self, *args, **kwargs):
# 调用函数之前,做点什么
result = self.funcation(*args,**kwargs)
# 在调用之后做点什么并且返回结果
return result
# -*- coding: utf-8 -*-
# 带参数的类装饰器(和不带参数的类装饰器有很大的不同)
# 类装饰器的实现,必须实现__call__和__init__两个内置函数。
# __init__:不再接收被装饰函数,而是接收传入参数;
# __call__:接收被装饰函数,实现装饰逻辑
class logger(object):
def __init__(self, level='INFO'):
self.level = level
def __call__(self, func):
def wrapper(*args, **kwargs):
print("[{level}]: the function {func}() is running...".format(level=self.level, func=func.__name__))
func(*args, **kwargs)
return wrapper
@logger(level="WARNING")
def say(something):
print("say {}!".format(something))
say("hello")