元类与装饰器的混合应用
程序员文章站
2022-06-17 07:54:48
...
对于装饰器来说,如果要使用那么@装饰器 .
如果现在1或N个类中的所有方法全要使用装饰器,怎么办呢. 这时元类就能帮上忙了,元类是创建类的一个类,可以在创建类的过程中把所有的装饰器安装在所有的类方法上.
首先是正常的装饰器语法:
import time
from types import FunctionType
#一个用于计时的简单装饰器
def timer(label = '',tracer = True):
def decorator(func):
def on_call(*args,**kwargs):
start = time.clock()
result = func(*args,**kwargs)
now = time.clock()
elapsed = now - start
on_call.alltime += elapsed
if tracer:
format = '%s%s: %.5f %.5f'
formatvalues = (label,func.__name__,elapsed,on_call.alltime)
print(format%formatvalues)
return result
on_call.alltime = 0
return on_call
return decorator
class Person:
def __init__(self,name='0x',age = 1):
self.name = name
self.age = age
@timer() #正常的装饰器语法
def lastName(self):
return self.name.split()[-1]
p = Person()
p.lastName()
混合:
#先创建一个metaclass , 继承type
#重定义__new__ , 实际参数是(meta,classname,supers,classdict)
#循环classDict,把方法重定向, 相当于使用了装饰器
class MetaPerson(type):
def __new__(cls, *args, **kwargs):
print('元类本身:',cls)
print('类的命名空间词典:',args[2])
classDict = args[2]
for attr,value in classDict.items():
if type(value) is FunctionType:
classDict[attr] =timer()(value)
print('类创建完成')
return type.__new__(cls,*args,**kwargs)
class Person(metaclass=MetaPerson):
def __init__(self,name='0x',age = 1):
self.name = name
self.age = age
#@timer() #正常的装饰器语法
def lastName(self):
return self.name.split()[-1]
进阶一下 , 混合应用:
#装饰器与元类的混合应用2
#上面例子中只能使用一个装饰器
#可以用利用闭包来增加一个装饰器参数
def decorator_methods(decorator): #接受一个装饰器
class MetaClass(type): #一个元类
def __new__(cls, *args, **kwargs):
print('元类:',cls)
classDict = args[2]
for attr, value in classDict.items():
if type(value) is FunctionType: #只要是一个函数的话, 可以自己判断额外的
classDict[attr] = decorator(value) #使用装饰器,装饰方法
return type.__new__(cls,*args,**kwargs)
return MetaClass
class Person(metaclass=decorator_methods(timer())):
def __init__(self,name='0x',age = 1):
self.name = name
self.age = age
#@timer() #正常的装饰器语法
def lastName(self):
return self.name.split()[-1]
p = Person()
p.lastName()
同样的上述方法也可以使用装饰器来实现:
#同样的可以使用装饰器来实现
def deco(decorator): #接受一个装饰器
def on_deco(aClass): #接受一个类对象.
for attr, value in aClass.__dict__.items():
if type(value) is FunctionType:
setattr(aClass,attr,decorator(value)) #注意,这里使用setattr, 不要使用aClass.__dict__ 来赋值.
return aClass #因为这里类对象已经创建完了
return on_deco
@deco(timer())
class Person:
def __init__(self,name='0x',age = 1):
self.name = name
self.age = age
#@timer() #正常的装饰器语法
def lastName(self):
return self.name.split()[-1]
p = Person()
p.lastName()
推荐阅读
-
Bottle框架中的装饰器类和描述符应用详解
-
类的封装,类内的方法装饰器,类的方法修改与删除装饰器,经典类和新式类
-
元类与装饰器的混合应用
-
Bottle框架中的装饰器类和描述符应用详解
-
闭包的原理与经典应用场景,访问器属性,类与对象的创建与成员引用,数组与对象的解构过程与经典案例,JS引入到浏览器中的的方法及获取DOM元素的两个API
-
闭包的原理与经典应用场景 、访问器属性、类与对象的创建与成员引用 、数组与对象的解构、JS引入到浏览器中的的方法
-
闭包的原理与经典应用场景,访问器属性,类与对象的创建与成员引用,数组与对象的解构过程与经典案例,JS引入到浏览器中的的方法及获取DOM元素的两个API
-
闭包、访问器属性、类与对象的创建和解析、JS浏览器应用
-
闭包、访问器属性、类与对象的创建和解析、JS浏览器应用
-
类的封装,类内的方法装饰器,类的方法修改与删除装饰器,经典类和新式类