python闭包是装饰器的真子集,即装饰器是更加宽泛的概念。
装饰器的目的:代码重用+额外功能
闭包的主要目的:保存函数的运行环境+保存闭包的局部变量。
**总结:**函数装饰器不管是装饰函数、还是装饰类,所遵循的思想原理是一样的,实现的方式也是大同小异。**注意,**函数装饰器装饰类,实际上是装饰类的构造函数!
总结:实际上类装饰器所实现的功能在原理上和函数装饰器也没有太大的区别,但是在代码实现上有所区别,主要体现在两方面:
第一:类装饰器的构造函数__init__就相当于是第一层(外层)的decorator,传入需要装饰的对象作为参数;
第二:类装饰器的魔法方法__call__相当于是第二层(内层)的wrapper,注意参数要统一,有返回值需要返回值。
**注意:**类装饰器,对象调用__call__是不可或缺的。
装饰器的缺点总结:
(1)被函数装饰器所装饰的对象(函数、类)已经不再是它本身了,虽然从形式上看没有变化,本质上是函数装饰器的内部wrapper;
(2)被类装饰器所装饰的对象(函数、类)也不再是它本身了,虽然从形式上看没有变化,本质上是类装饰器的一个对象。
装饰是为函数和类指定管理或扩增代码的一种方式。装饰器本身采取可调用对象的形式并处理其他可调用对象。
装饰器语法糖:在def语句结束时通知另一个函数来运行这个函数,把最初的函数名重新绑定到返回的结果。
装饰器不但能管理类和函数的调用,也能管理类和函数本身,添加属性等。
简而言之,装饰器提供了一种方法,在函数和类定义语句结束时插入自动运行的代码。
装饰器自身是一个返回可调用对象的可调用对象。
类装饰器自动的传递类给装饰器函数,之后装饰器的结果分配回给类名。
函数装饰器
//函数作为函数的装饰器
//无参装饰器
def decorator(fun):
def wrapper(*args,**kwargs):
return fun(*args,**kwargs)
return wrapper
//有参装饰器
def decorator(*dec_args,**dec_kwargs):
def wrapper(func):
def inner(*args,**kwargs):
return func(*args,**kwargs)
return inner
return wrapper
//函数中类作为实际装饰器装饰函数
def decorator(*args,**kwargs):
class WrapClass:
def __init__(self,func):
self.func = func
def __call__(self,*args,**kwargs):
self.func(*args,**kwargs)
return WrapClass
//类作为函数的装饰器
//无参装饰器
class Decorator:
def __init__(self,func):
self.func = func
def __call__(self,*args,**kwargs):
self.func(*args,**kwargs)
//函数作为类的装饰器
//单例 instances 与局部instance两种方式
instances = {}
def singleton(aClass):
instance = None
def onCall(*args,**kwargs):
nonlocal instance
if aClass in instances:
instance = aClass(*args,**kwargs)
instances[aClass] = aClass(*args,**kwargs)
return instances[aClass]
return onCall
//给类实例添加装饰
def decorator(aClass):
class Wrapper:
def __init__(self,*args,**kwargs):
self.wrapped = aClass(*args,**kwargs)
def __getattr__(self,attrname):
return getattr(self.wrapped,attrname)
return Wrapper