1. 程式人生 > >從pyh看Python的工廠模式

從pyh看Python的工廠模式

【設想】

在做selenium前端頁面測試時,想到生成html報告,需要編寫個類,實現在Python內編輯html,具體思路如下:

1、編寫各種tag型別,如head、title、body;

2、過載 + 運算,實現類似html + head的功能;

【PyH工廠模式解析】

PyH就一個原始碼pyh.py,很簡單,以下擷取部分程式碼分析,請尊重原作者,不要直接使用

定義一個基礎類,並重載+操作符,過載<<過載符

class Tag(list):
    tagname = ''
    
    def __init__(self, *arg, **kw):
        self.attributes = kw
        if self.tagname : 
            name = self.tagname
            self.isSeq = False
        else: 
            name = 'sequence'
            self.isSeq = True
        self.id = kw.get('id', name)
        #self.extend(arg)
        for a in arg: self.addObj(a)

    def __iadd__(self, obj):
        if isinstance(obj, Tag) and obj.isSeq:
            for o in obj: self.addObj(o)
        else: self.addObj(obj)
        return self
    
    def addObj(self, obj):
        if not isinstance(obj, Tag): obj = str(obj)
        id=self.setID(obj)
        setattr(self, id, obj)
        self.append(obj)

    def setID(self, obj):
        if isinstance(obj, Tag):
            id = obj.id
            n = len([t for t in self if isinstance(t, Tag) and t.id.startswith(id)])
        else:
            id = 'content'
            n = len([t for t in self if not isinstance(t, Tag)])
        if n: id = '%s_%03i' % (id, n)
        if isinstance(obj, Tag): obj.id = id
        return id

    def __add__(self, obj):
        if self.tagname: return Tag(self, obj)
        self.addObj(obj)
        return self

    def __lshift__(self, obj):
        self += obj
        if isinstance(obj, Tag): return obj

    def render(self):
        result = ''
        if self.tagname:
            result = '<%s%s%s>' % (self.tagname, self.renderAtt(), self.selfClose()*' /')
        if not self.selfClose():
            for c in self:
                if isinstance(c, Tag):
                    result += c.render()
                else: result += c
            if self.tagname: 
                result += '</%s>' % self.tagname
        result += '\n'
        return result

    def renderAtt(self):
        result = ''
        for n, v in self.attributes.iteritems():
            if n != 'txt' and n != 'open':
                if n == 'cl': n = 'class'
                result += ' %s="%s"' % (n, v)
        return result

    def selfClose(self):
        return self.tagname in selfClose        

然後定義工廠類
def TagFactory(name):
    class f(Tag):
        tagname = name
    f.__name__ = name
    return f

最後實現工廠模式
for t in tags: setattr(thisModule, t, TagFactory(t)) 

【PyH生成html】

#生成一個page物件
report_html = PyH(ur'樂視頁面測試報告')
'''可以使用<<運算子往page類新增tag節點,可新增的如下
tags = ['html', 'body', 'head', 'link', 'meta', 'div', 'p', 'form', 'legend', 
        'input', 'select', 'span', 'b', 'i', 'option', 'img', 'script',
        'table', 'tr', 'td', 'th', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
        'fieldset', 'a', 'title', 'body', 'head', 'title', 'script', 'br', 'table',
        'ul', 'li', 'ol']
'''
report_html << h1(u'樂視頁面測試報告',cl='header1',style='color:red; text-align:center')
#Tag物件,也可以使用<<往裡面新增節點
myul = report_html << ul(cl='ul_report')
logintb = myul << table(cl='tb_login',border=2)
logintb << tr(cl='tb_tr') << td(cl='tb_login_head') << p(u'登入測試用例: 1 個',style='color:blue; text-align:center')
#最後使用printOut輸出到檔案或者console
report_html.printOut('result.html')