20.python笔记之装饰器
装饰器
装饰器是函数,只不过该函数可以具有特殊的含义,装饰器用来装饰函数或类,使用装饰器可以在函数执行前和执行后添加相应操作。
装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志、性能测试、事务处理等。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
例:如果一个公司有运维部,开发部,测试部,设计部,等,并且公司具有基础平台架构,为公司各个部门提供数据库调用,资料查看,监控等。当这些部门想使用这些功能的时候,直接调用这些功能的接口就可以,如下:
基础平台提供的功能------------
def 功能1()
print ('功能1')
def 功能2()
print ('功能2')
def 功能3()
print ('功能3')
def 功能4()
print ('功能4')
当运维部门调用的时候如下:
def 功能1()
def 功能2()
def 功能3()
当开发部门调用的时候如下:
def 功能1()
def 功能2()
def 功能3()
之后要为平台提供的所有功能添加验证机制,
基础平台提供如下功能接口:
1.让各个部门修改自己的代码
2.在每个部门实现的功能上加上代码
3.把验证代码变成函数 在每个功能上加入
4.为了追寻开放封闭原则
利用装饰器的功能实现
def login(func):
def inner():
# 验证1
# 验证2
# 验证3
return func()
return inner
@login
def 功能1():
print ('功能1')
@login
def 功能2():
print ('功能2')
@login
def 功能3():
print ('功能3')
@login
def 功能4():
print ('功能4')
当各个部门执行def功能的时候
def login(func):
def inner():
# 验证1
return func()
return inner
@login
def 功能1():
print '功能1'
当调用功能1的时候 会先把功能1的函数名带入内存地址,之后会执行login函数,func为功能1,之后inner会将功能1的参数带入等待执行inner的验证功能后,会将参数交给func执行功能1的命令。
例:
第一步:最简单的函数,准备附加额外功能
def myfunc():
print("调用myfunc().")
myfunc()
myfunc()
结果:
调用myfunc().
调用myfunc().
第二步:使用装饰函数在函数执行前和执行后分别附加额外功能
def deco(func):
print("执行装饰器函数1")
func() #将func的内存地址执行
print("执行装饰器函数2")
return func #返回函数
def myfunc():
print(" 执行myfunc函数")
#执行deco函数的时候会把myfunc函数的内存地址带入
myfunc = deco(myfunc)
print(myfunc)
结果:
执行装饰器函数1
执行myfunc函数
执行装饰器函数2
<function myfunc at 0x0000000000BDA6A8>
第三步:使用语法糖@来装饰函数
def deco(func):
print("装饰器开始")
func()
print("装饰器结束")
return func
@deco
def myfunc():
print("我只是一个普通的函数")
或者:
def deco(func):
user = input('user:')
passwd = input('pass:')
print('验证成功')
func()
return func
#注func函数就是myfunc函数 当装饰器全部执行之后再执行func函数
@deco
def myfunc():
print("欢迎使用京猫平台")
第四步:使用内嵌包装函数来确保每次新函数都被调用
#内嵌包装函数的形参和返回值与原函数相同,装饰函数返回内嵌包装函数对象'''
def deco(func):
def _deco():
user = input('user:')
passwd = input('pass')
print('用户和密码正确')
func()
# 不需要返回func,实际上应返回原函数的返回值
return _deco
@deco
def login():
print("登录成功")
return 'ok'
#login函数可以重复调用多次,每次调用的时候,都会先执行装饰器里的函数,
login()
第五步:对带参数的函数进行装饰
#内嵌包装函数的形参和返回值与原函数相同,装饰函数返回内嵌包装函数对象'''
def deco(func):
def _deco(a, b):
ret = func(a, b)
return ret
return _deco
@deco
def myfunc(a, b):
print(" 函数%s+%s." % (a, b))
return a + b
myfunc(1, 2)
myfunc(3, 4)
#当我执行myfunc带参数的时候调用装饰器函数
第六步:对参数数量不确定的函数进行装饰
#参数用(*args, **kwargs),自动适应变参和命名参数'''
def deco(func):
def _deco(*args, **kwargs): #*agrs和**kwargs是普通函数的参数
print("普通函数名:%s" % func.__name__)
#执行普通函数
ret = func(*args, **kwargs)
print("普通函数%s执行结果为%s" % (func.__name__, ret))
return ret
return _deco
@deco
def myfunc(a, b):
print("普通函数1%s+%s" % (a, b))
return a+b
@deco
def myfunc2(a, b, c):
print("普通函数2%s+%s+%s" % (a, b, c))
return a+b+c
myfunc(1, 2)
myfunc(3, 4)
myfunc2(1, 2, 3)
myfunc2(3, 4, 5)
**第七步:让装饰器带参数**
#装饰函数名实际上应更有意义些'''
def deco(arg):
def _deco(func):
def __deco():
print("普通函数名 %s 装饰器参数名 [%s]." % (func.__name__, arg))
func()
print("普通函数名 %s 装饰器参数名 [%s]." % (func.__name__, arg))
return __deco
return _deco
@deco("装饰器参数1")
def myfunc():
print("普通函数1")
@deco("装饰器参数2")
def myfunc2():
print("普通函数2")
myfunc()
myfunc2()
第八步:装饰器带 类 参数
class locker:
def __init__(self):
print("这个是.__init__().")
@staticmethod
def acquire():
print("(这是静态方法)")
@staticmethod
def release():
print("(不需要对象实例)")
def deco(cls):
'''cls 必须实现acquire和release静态方法'''
def _deco(func):
def __deco():
print("函数名: %s 类:[%s]." % (func.__name__, cls))
cls.acquire()
try:
return func()
finally:
cls.release()
return __deco
return _deco
@deco(locker)
def myfunc():
print("普通函数")
myfunc()
**第九步:装饰器带类参数,并分拆公共类到其他py文件中,同时演示了对一个函数应用多个装饰器**
1.melocker.py(公共类文件)
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):
'''cls 必须实现acquire和release静态方法'''
def _deco(func):
def __deco(*args, **kwargs):
print("before %s called." % func.__name__)
cls.acquire()
try:
return func(*args, **kwargs)
finally:
cls.unlock()
return __deco
return _deco
2.使用装饰器文件
#!/usr/bin/env python3
#coding:utf8
from melocker import *
class example:
@lockhelpermelocker)
def myfunc(self):
print(" myfunc() called.")
@lockhelper(melocker)
@lockhelper(lockerex)
def myfunc2(self, a, b):
print(" myfunc2() called.")
return a + b
if __name__=="__main__":
a = example()
a.myfunc()
print(a.myfunc())
print(a.myfunc2(1, 2))
print(a.myfunc2(3, 4))
完毕!!!