元类与装饰器


元类与装饰器的关系
<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>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 装饰是为函数和类指定管理代码的一种方式.装饰器本身的形式是处理其他的可调用对象的可调用的对象。 函数装饰器在函数定...
    低吟浅唱1990阅读 236评论 0 0
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,026评论 19 139
  • 学习一下几个内容 __getattr__和__setattr__方法,把未定义的属性获取和所有的属性赋值指向通用的...
    低吟浅唱1990阅读 423评论 0 0
  • 20- 枚举,枚举原始值,枚举相关值,switch提取枚举关联值 Swift枚举: Swift中的枚举比OC中的枚...
    iOS_恒仔阅读 2,320评论 1 6
  • 基础1.r''表示''内部的字符串默认不转义2.'''...'''表示多行内容3. 布尔值:True、False(...
    neo已经被使用阅读 1,741评论 0 5