Python 中的元类编程(3)
2008-09-30 12:42:40 来源:WEB开发网 闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁炬儳缍婇弻鐔兼⒒鐎靛壊妲紒鐐劤缂嶅﹪寮婚悢鍏尖拻閻庨潧澹婂Σ顔剧磼閹冣挃闁硅櫕鎹囬垾鏃堝礃椤忎礁浜鹃柨婵嗙凹缁ㄧ粯銇勯幒瀣仾闁靛洤瀚伴獮鍥敍濮f寧鎹囬弻鐔哥瑹閸喖顬堝銈庡亝缁挸鐣烽崡鐐嶆棃鍩€椤掑嫮宓佸┑鐘插绾句粙鏌涚仦鎹愬闁逞屽墰閹虫捇锝炲┑瀣╅柍杞拌兌閻ゅ懐绱撴担鍓插剱妞ゆ垶鐟╁畷銉р偓锝庡枟閻撴洘銇勯幇闈涗簼缂佽埖姘ㄧ槐鎾诲礃閳哄倻顦板┑顔硷工椤嘲鐣烽幒鎴旀瀻闁规惌鍘借ⅵ濠电姷鏁告慨顓㈠磻閹剧粯鈷戞い鎺嗗亾缂佸鏁婚獮鍡涙倷閸濆嫮顔愬┑鐑囩秵閸撴瑦淇婇懖鈺冪<闁归偊鍙庡▓婊堟煛鐏炵硶鍋撻幇浣告倯闁硅偐琛ラ埀顒冨皺閺佹牕鈹戦悙鏉戠仸闁圭ǹ鎽滅划鏃堟偨缁嬭锕傛煕閺囥劌鐏犻柛鎰ㄥ亾婵$偑鍊栭崝锕€顭块埀顒佺箾瀹€濠侀偗婵﹨娅g槐鎺懳熺拠鑼舵暱闂備胶枪濞寸兘寮拠宸殨濠电姵纰嶉弲鎻掝熆鐠虹尨宸ョ€规挸妫濆铏圭磼濡搫顫嶇紓浣风劍閹稿啿鐣烽幋锕€绠婚悹鍥у级瀹撳秴顪冮妶鍡樺鞍缂佸鍨剁粋宥夋倷椤掍礁寮垮┑鈽嗗灣閸樠勭妤e啯鍊垫慨妯煎亾鐎氾拷

另一点需要注意的是,Enhance() 函数的功能远不只上面提到的简单版本。装饰器更擅长完成复杂的增强功能。例如,以下是一个将 “记录” 添加到类的 Enhance() 函数:
清单 13. 类增强的变体
@classinitializer
def def_properties(cls, schema):
"""
Add properties to cls, according to the schema, which is a list
of pairs (fieldname, typecast). A typecast is a
callable converting the field value into a Python type.
The initializer saves the attribute names in a list cls.fields
and the typecasts in a list cls.types. Instances of cls are expected
to have private attributes with names determined by the field names.
"""
cls.fields = []
cls.types = []
for name, typecast in schema:
if hasattr(cls, name): # avoid accidental overriding
raise AttributeError('You are overriding %s!' % name)
def getter(self, name=name):
return getattr(self, '_' + name)
def setter(self, value, name=name, typecast=typecast):
setattr(self, '_' + name, typecast(value))
setattr(cls, name, property(getter, setter))
cls.fields.append(name)
cls.types.append(typecast)
不同之处在于:(a)什么被增强了;(b)这种方法是如何工作的;(c)基类的工作都保持正交:
清单 14. 自定义记录类
>>> class Article(object):
... # fields and types are dynamically set by the initializer
... def_properties([('title', str), ('author', str), ('date', date)])
... def __init__(self, values): # add error checking if you like
... for field, cast, value in zip(self.fields, self.types, values):
... setattr(self, '_' + field, cast(value))
>>> a=Article(['How to use class initializers', 'M. Simionato', '2006-07-10'])
>>> a.title
'How to use class initializers'
>>> a.author
'M. Simionato'
>>> a.date
datetime.date(2006, 7, 10)
更多精彩
赞助商链接