动态语言就是动态语言,还是要改变思路。。
废话不说直接看这个例子,请注意Dumper这个类的实现,好吧,其实我说的是self.dump(msg)这一句。
class DumpToScreen(object): def dump(self, msg): print "Message:", msg class Dumper(object): def log(self, msg): self.dump(msg) class ErrorHandler(Dumper, DumpToScreen): def dump_error(self, msg): self.log(msg) e = ErrorHandler()e.dump_error("Alert!")?看明白了没?直接实例化Dumper然后调用log方法一定会抛异常(因为dump方法在Dumper中不存在),但是如果在ErrorHandler中调用就可以了,因为ErrorHandler是一个多继承,另外一条继承树上的DumpToScreen类实现了dump方法,把error message打印到console。
?
这就是传说中Python的Mixin。。。。DumpToScreen这个类一个比较好的命名实际上是DumpToScreenMixin,你也可以自己实现DumpToFileMixin,DumpToSkyDriveMixin,blahblahblah,然后在不更改ErrorHandler类内部逻辑的情况下天马行空任意扩充它的功能。
?
产生这个问题,源自于看Tornado的OAuth部分的代码,思维停留在编译型语言的我一下蒙了。比如,举一个例子,来自tornado:
class OAuth2Mixin(object): def authorize_redirect(self, redirect_uri=None, client_id=None, client_secret=None, extra_params=None): args = { "redirect_uri": redirect_uri, "client_id": client_id } if extra_params: args.update(extra_params) self.redirect( url_concat(self._OAUTH_AUTHORIZE_URL, args)) def _oauth_request_token_url(self, redirect_uri=None, client_id=None, client_secret=None, code=None, extra_params=None): url = self._OAUTH_ACCESS_TOKEN_URL args = dict( redirect_uri=redirect_uri, code=code, client_id=client_id, client_secret=client_secret, ) if extra_params: args.update(extra_params) return url_concat(url, args)?