`
zuroc
  • 浏览: 1290149 次
  • 性别: Icon_minigender_1
  • 来自: 江苏
社区版块
存档分类
最新评论

《在路上 …》 写代码也需要一点演技 – python2.6 的 class decorator

阅读更多

写通用的回复类, 原本打算做成一个独立的基类


class ReplyBase(object):

    _REPLY_REALTED_CLS = None                                                              

    _REPLY_CLS = None                                                               

    mc_reply_id_by_rid = McLimitA(                                                  

        "ReplyIdBy%sId:%%s"%_REPLY_RCLS.Meta.table.title(),                         

        128                                                                         

    )

    ...


写下来以后, 忽然想到        


"ReplyIdBy%sId:%%s"%_REPLY_RCLS.Meta.table.title(),                         


在基类定义的时候就被确定了, 不好搞


这样下去就只有用Meta Class


不过正如 洪教授 所言 ( http://www.infoq.com/cn/interviews/douban-hqn )


Meta Class 是种黑魔法, 正派人士都很畏惧它.


虽然有部YY小说, 标题叫做"魔本是道", 不过这也就是纯属意淫, 估计连本实体书都没有.


正如我昨天说过的 做人需要一点演技( http://www.douban.com/note/101804926/ )


写代码也不能太暴露内心的邪恶念头.


decorator, 正如其名, 装饰器, "装"是核心词, 是我圣教中人, 行走江湖必备的技能. 


好吧, 过去我常常以"张教主"自诩, 不过一晃也有很多年没进行官方的正式声明了. 


江湖儿女江湖老,昏昏灯火忆平生.


言归正传, 先来做一个小实验, 用函数动态添加一个基类


class C(object):

    def x(self):

        return self.__class__


class B(object):

    pass


class A(B):

    pass


def main():

    print "A.__bases__ before", A.__bases__

    A.__bases__ = tuple(list(A.__bases__)+[C, ])

    print "A.__bases__ after", A.__bases__

    print "A().x()", A().x()


输出是


A.__bases__ before (<class '__main__.B'>,)

A.__bases__ after (<class '__main__.B'>, <class '__main__.C'>)

A().x() <class '__main__.A'>


人体试验很成功, 我很开心


当然, 我这里有些细节懒得交代了, 我是工科生, 不是理科生, 我只追求可以work的solution, 不考究背后theory. 何况我本科文凭中还有"医学"两个字符.


医学是只看结果不问过程的.


不过, 如果你遇到什么问题, 可以从这里开始探索 http://blog.donews.com/limodou/archive/2005/01/06/227676.aspx


说了这么多, 还是直接上代码吧, 代码是很无趣. 就像武功秘籍一样.


找秘籍的人永远很多, 炼成的永远很少.


这还是精简演示版, 很多接口没做.


如果说Meta Class是基因改造,  class decorator就像是整容手术了. 下面正式开工


=================================================


#!/usr/bin/env python

#coding:utf-8

from init_db import McModel, McCacheA, McCache, Model, mc, cursor_by_table, McLimitA

from const.man import STATE_DEL, STATE_APPLY, STATE_ACTIVE, STATE_BAN


class ReplyMixin(object):

    def new_reply(self, man_id, txt, state=STATE_ACTIVE):

        rid = self.id

        self.reply_count += 1

        self.save()

        s = self._REPLY_CLS(rid=rid, man_id=man_id, state=state)

        s.txt = txt

        s.save()

        self.mc_reply_id_by_rid.delete(rid)

        return s



    def reply_list(self, offset, limit):

        return self._REPLY_CLS.mc_get_list(

            self.reply_id_list(offset, limit)

        )


def mixin_reply(reply_cls):

    """

@mixin_reply(XxxReply)

class Xxx(McModel):

    pass

    """

    def _(cls):

        cls.__bases__ = tuple(list(cls.__bases__)+[ReplyMixin, ])

        cls.mc_reply_id_by_rid = McLimitA(

            "ReplyIdBy%sId#%%s"%cls.Meta.table.title(),

            128

        )

        cls._REPLY_CLS = reply_cls

        cls.reply_id_list = cls.mc_reply_id_by_rid("{self.id}")(

            reply_id_list

        )

        return cls

    return _


def reply_id_list(self, offset, limit):

    c = self._REPLY_CLS.raw_sql(

        "select id from " +

        self._REPLY_CLS.Meta.table +

        " where rid=%s and state>%s order by create_time limit %s offset %s",

        self.id, STATE_APPLY, limit, offset

    )

    return [i for i, in c.fetchall()]




=============================


同时为了统一管理, 迁移原来的一些reply函数到新代码上, 但是保留原接口


=============================


--- mysite/model/review.py (revision 3071)

+++ mysite/model/review.py (working copy)


+from reply import mixin_reply

 

 

 class ReviewReply(McModel):

     pass

 

+@mixin_reply(ReviewReply)

class Review(McModel):

    txt = review_txt.property

 

 def review_reply_by_review_id(id, offset, limit):

-    return ReviewReply.mc_get_list(

-        review_reply_id_by_review_id(id, offset, limit)

+    return Review(id).reply_list(

+        offset, limit

     )

 

 def review_reply_new(review_id, man_id, txt, state=STATE_ACTIVE):

     r = Review.mc_get(review_id)

-    if r:

-        r.reply_count += 1

-        r.save()

-        s = ReviewReply(rid=review_id, man_id=man_id, state=state)

-        s.txt = txt

-        s.save()

-        mc_review_reply_id_by_review_id.delete(s.id)

-        return s

+    return r.new_reply(man_id,txt,state)




文章同步自 http://kanrss.com/~onway/t/110
同步程序见 这里
作者 张沈鹏



分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics