欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

元类与装饰器的混合应用

程序员文章站 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()

相关标签: 元类 装饰器