元类与装饰器的关系
<li>在class语句的末尾,类装饰器把类名重新绑定到一个函数的结果。
<li>元类通过一条class语句的末尾把类对象创建过程路由到一个对象来工作
<pre>
装饰器实现添加来个方法
def extender1(aClass):
aClass.eggs = eggsfunc
aClass.ham = hamfunc
return aClass
@extender1
class Client2:
def __init__(slef,value):
slef.value = value
def spam(slef):
return slef.value * 2
if __name__ == '__main__':
x = Client2('Ni!')
print(x.spam())
print(x.eggs())
print(x.ham('hh'))
</pre>
类装饰器常常和元类一样充当类管理角色。元类往往和装饰器一样充当实例管理的角色。
<li>类装饰器可以管理类和实例
<li>元类可以管理类和实例,但是管理实力需要一些额外工作
工具方法
<pre>
--coding:UTF-8--
def tracer(func):
calls = 0
def onCall(args,kwargs):
nonlocal calls
calls += 1
print('call %s to %s'%(calls,func.__name__))
return func(args,**kwargs)
return onCall
import time
def timer(label='',trace = True):
def onDecorator(func):
def onCall(args,kwargs):
start = time.clock()
result = func(args,**kwargs)
elapsed = time.clock() - start
onCall.alltime += elapsed
if trace:
format = '%s%s:%.5f,%.5f'
values = (label,func.__name__,elapsed,onCall.alltime)
print(format%values)
return result
onCall.alltime = 0
return onCall
return onDecorator
</pre>
对方法使用装饰器
<pre>
--coding:UTF-8--
from mytools import tracer
class Person:
@tracer
def __init__(self,name,pay):
self.name = name
self.pay = pay
@tracer
def giveRaise(self,percent):
self.pay *= (1.0+percent)
@tracer
def lastName(self):
return self.name.split()[-1]
if __name__ == 'main':
bob= Person('Bob Smoth',5000)
print(bob.name)
bob.giveRaise(.10)
print(int(bob.pay))
print(bob.lastName())
</pre>
使用元类和装饰器
<pre>
--coding:UTf-8--
from types import FunctionType
from mytools import tracer
class MetaTrace(type):
def __new__(meta,classname,supers,classdict):
for attr,attrval in classdict.items():
print(attr,attrval,sep='\n...') #输出细节
if type(attrval) is FunctionType:
classdict[attr] = tracer(attrval) #为每个方法添加装饰器
return type.__new__(meta,classname,supers,classdict)
class Person(metaclass = MetaTrace):
def __init__(self,name,pay):
self.name = name
self.pay = pay
def giveRaise(self,percent):
self.pay *= (1.0+percent)
def lastName(self):
return self.name.split()[-1]
if __name__ == '__main__':
bob = Person('Bob Rebort',50000)
bob.giveRaise(.10)
print(int(bob.pay))
print(bob.lastName())
__module__
...__main__
__qualname__
...Person
giveRaise
...<function Person.giveRaise at 0x004BA270>
__init__
...<function Person.__init__ at 0x004BA228>
lastName
...<function Person.lastName at 0x004BA348>
call 1 to __init__
call 1 to giveRaise
55000
call 1 to lastName
Rebort
在类创建的时候,元类自动把函数装饰器应用于每个方法,并且函数装饰器自动拦截方法调用,以便在此输出中打印出跟踪消息
</pre>
把任何装饰器应用与方法
<pre>
def decorateAll(decorator):
class MetaDecorate(type):
def __new__(meta,classname,supers,classdict):
for attr,attrval in classdict.items():
if type(attrval) is FunctionType:
classdict[attr] = decorator(attrval)
return type.__new__(meta,classname,supers,classdict)
return MetaDecorate
class Person(metaclass = decorateAll(tracer)):...
</pre>
类装饰器
<pre>
def decorateAll(decorator):
def decodecorator(aClass):
for attr,attrval in aClass.dict.items():
if type(attrval) is FunctionType:
setattr(aClass,attr,decorator(attrval))
return aClass
return decodecorator
@decorateAll(tracer)
class Person:...
类装饰器返回最初的、扩展的类,而不是其包装层。
这个类装饰器只是处理了类的创建、实例创建调用根本没有拦截
</pre>