python的即時戳印金鑰目練習筆記

來源:互聯網
上載者:User
這是《python基礎教程》後面的實踐,照著寫寫,一方面是來熟悉python的代碼方式,另一方面是練習使用python中的基本的以及非基本的文法,做到熟能生巧。

這個項目一開始比較簡單,不過重構之後就有些複雜了,但是更靈活了。

按照書上所說,重構之後的程式,分為四個模組:處理常式模組,過濾器模組,規則(其實應該是處理規則),文法分析器。

先來說處理常式模組,這個模組的作用有兩個,一個是提供那些固定的html標記的輸出(每一個標記都有start和end),另一個是對這個標記輸出的開始和結束提供了一個友好的提供者。來看下程式handlers.py:

代碼如下:


class Handler:
'''
'''
def callback(self, prefix, name, *args):
method = getattr(self,prefix+name,None)
if callable(method): return method(*args)
def start(self, name):
self.callback('start_', name)
def end(self, name):
self.callback('end_', name)
def sub(self, name):
def substitution(match):
result = self.callback('sub_', name, match)
if result is None: match.group(0)
return result
return substitution

class HTMLRenderer(Handler):
'''

'''
def start_document(self):
print '...'
def end_document(self):
print ''
def start_paragraph(self):
print '

'
def end_paragraph(self):
print '

'
def start_heading(self):
print '

'
def end_heading(self):
print '

'
def start_list(self):
print '
    '
    def end_list(self):
    print '
'
def start_listitem(self):
print '
  • '
    def end_listitem(self):
    print '
  • '
    def start_title(self):
    print '

    '
    def end_title(self):
    print '

    '
    def sub_emphasis(self, match):
    return ' %s' % match.group(1)
    def sub_url(self, match):
    return '%s' % (match.group(1),match.group(1))
    def sub_mail(self, match):
    return '%s' % (match.group(1),match.group(1))
    def feed(self, data):
    print data

    這個程式堪稱是整個“項目”的基石所在:提供了標籤的輸出,以及字串的替換。理解起來也比較簡單。

    再來看第二個模組“過濾器”,這個模組更為簡單,其實就是一個Regex的字串。相關代碼如下:

    代碼如下:


    self.addFilter(r'\*(.+?)\*', 'emphasis')
    self.addFilter(r'(http://[\.a-z0-9A-Z/]+)', 'url')
    self.addFilter(r'([\.a-zA-Z]+@[\.a-zA-Z]+[a-zA-Z]+)','mail')

    這就是三個過濾器了,分別是:強調牌過濾器(用×號標出的),url牌過濾器,email牌過濾器。熟悉Regex的同學理解起來是沒有壓力的。

    再來看第三個模組“規則”,這個模組,拋開那祖父類不說,其他類應該有的兩個方法是condition和action,前者是用來判斷讀進來的字串是不是符合自家規則,後者是用來執行操作的,所謂的執行操作就是指調用“處理常式模組”,輸出前標籤、內容、後標籤。 來看下這個模組的代碼,其實這個裡面幾個類的關係,畫到類圖裡面看會比較清晰。 rules.py:

    代碼如下:


    class Rule:
    def action(self, block, handler):
    handler.start(self.type)
    handler.feed(block)
    handler.end(self.type)
    return True

    class HeadingRule(Rule):
    type = 'heading'
    def condition(self, block):
    return not '\n' in block and len(block) <= 70 and not block[-1] == ':'

    class TitleRule(HeadingRule):
    type = 'title'
    first = True

    def condition(self, block):
    if not self.first: return False
    self.first = False
    return HeadingRule.condition(self, block)

    class ListItemRule(Rule):
    type = 'listitem'
    def condition(self, block):
    return block[0] == '-'
    def action(self,block,handler):
    handler.start(self.type)
    handler.feed(block[1:].strip())
    handler.end(self.type)
    return True

    class ListRule(ListItemRule):
    type = 'list'
    inside = False
    def condition(self, block):
    return True
    def action(self,block, handler):
    if not self.inside and ListItemRule.condition(self,block):
    handler.start(self.type)
    self.inside = True
    elif self.inside and not ListItemRule.condition(self,block):
    handler.end(self.type)
    self.inside = False
    return False

    class ParagraphRule(Rule):
    type = 'paragraph'
    def condition(self, block):
    return True

    補充utils.py:

    代碼如下:


    def line(file):
    for line in file:yield line
    yield '\n'

    def blocks(file):
    block = []
    for line in lines(file):
    if line.strip():
    block.append(line)
    elif block:
    yield ''.join(block).strip()
    block = []

    最後隆重的來看下“文法分析器模組”,這個模組的作用其實就是協調讀入的文本和其他模組的關係。在往重點說就是,提供了兩個存放“規則”和“過濾器”的列表,這麼做的好處就是使得整個程式的靈活性得到了極大的提高,使得規則和過濾器變成的熱插拔的方式,當然這個也歸功於前面在寫規則和過濾器時每一種類型的規則(過濾器)都單獨的寫成了一個類,而不是用if..else來區分。 看代碼:

    代碼如下:


    import sys, re
    from handlers import *
    from util import *
    from rules import *

    class Parser:
    def __init__(self,handler):
    self.handler = handler
    self.rules = []
    self.filters = []

    def addRule(self, rule):
    self.rules.append(rule)

    def addFilter(self,pattern,name):
    def filter(block, handler):
    return re.sub(pattern, handler.sub(name),block)
    self.filters.append(filter)

    def parse(self, file):
    self.handler.start('document')
    for block in blocks(file):
    for filter in self.filters:
    block = filter(block, self.handler)
    for rule in self.rules:
    if rule.condition(block):
    last = rule.action(block, self.handler)
    if last:break
    self.handler.end('document')

    class BasicTextParser(Parser):
    def __init__(self,handler):
    Parser.__init__(self,handler)
    self.addRule(ListRule())
    self.addRule(ListItemRule())
    self.addRule(TitleRule())
    self.addRule(HeadingRule())
    self.addRule(ParagraphRule())

    self.addFilter(r'\*(.+?)\*', 'emphasis')
    self.addFilter(r'(http://[\.a-z0-9A-Z/]+)', 'url')
    self.addFilter(r'([\.a-zA-Z]+@[\.a-zA-Z]+[a-zA-Z]+)','mail')

    handler = HTMLRenderer()
    parser = BasicTextParser(handler)

    parser.parse(sys.stdin)

    這個模組裡面的處理思路是,遍曆用戶端(也就是程式執行的入口)給插進去的所有的規則和過濾器,來處理讀進來的文本。

    有一個細節的地方也要說一下,其實是和前面寫的呼應一下,就是在遍曆規則的時候通過調用condition這個東西來判斷是否符合當前規則。

    我覺得這個程式很像是命令列模式,有空可以複習一下該模式,以保持記憶網節點的牢固性。

    最後說一下我以為的這個程式的用途:

    1、用來做代碼高亮分析,如果改寫成js版的話,可以做一個線上代碼編輯器。
    2、可以用來學習,供我寫博文用。

    還有其他的思路,可以留下您的真知灼見。
    補充一個類圖,很簡陋,但是應該能說明之間的關係。另外我還是建議如果看代碼捋不清關係最好自己畫圖,自己畫圖才能熟悉整個結構。

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.