python的即時(shí)標(biāo)記項(xiàng)目練習(xí)筆記
這是《python基礎(chǔ)教程》后面的實(shí)踐,照著寫寫,一方面是來熟悉python的代碼方式,另一方面是練習(xí)使用python中的基本的以及非基本的語(yǔ)法,做到熟能生巧。
這個(gè)項(xiàng)目一開始比較簡(jiǎn)單,不過重構(gòu)之后就有些復(fù)雜了,但是更靈活了。
按照書上所說,重構(gòu)之后的程序,分為四個(gè)模塊:處理程序模塊,過濾器模塊,規(guī)則(其實(shí)應(yīng)該是處理規(guī)則),語(yǔ)法分析器。
先來說處理程序模塊,這個(gè)模塊的作用有兩個(gè),一個(gè)是提供那些固定的html標(biāo)記的輸出(每一個(gè)標(biāo)記都有start和end),另一個(gè)是對(duì)這個(gè)標(biāo)記輸出的開始和結(jié)束提供了一個(gè)友好的訪問接口。來看下程序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 '<html><head><title>...</title></head><body>'
def end_document(self):
print '</body></html>'
def start_paragraph(self):
print '<p>'
def end_paragraph(self):
print '</p>'
def start_heading(self):
print '<h2>'
def end_heading(self):
print '</h2>'
def start_list(self):
print '<ul>'
def end_list(self):
print '</ul>'
def start_listitem(self):
print '<li>'
def end_listitem(self):
print '</li>'
def start_title(self):
print '<h1>'
def end_title(self):
print '</h1>'
def sub_emphasis(self, match):
return '<em>%s</em>' % match.group(1)
def sub_url(self, match):
return '<a href="%s">%s</a>' % (match.group(1),match.group(1))
def sub_mail(self, match):
return '<a href="mailto:%s">%s</a>' % (match.group(1),match.group(1))
def feed(self, data):
print data
這個(gè)程序堪稱是整個(gè)“項(xiàng)目”的基石所在:提供了標(biāo)簽的輸出,以及字符串的替換。理解起來也比較簡(jiǎn)單。
再來看第二個(gè)模塊“過濾器”,這個(gè)模塊更為簡(jiǎn)單,其實(shí)就是一個(gè)正則表達(dá)式的字符串。相關(guān)代碼如下:
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')
這就是三個(gè)過濾器了,分別是:強(qiáng)調(diào)牌過濾器(用×號(hào)標(biāo)出的),url牌過濾器,email牌過濾器。熟悉正則表達(dá)式的同學(xué)理解起來是沒有壓力的。
再來看第三個(gè)模塊“規(guī)則”,這個(gè)模塊,拋開那祖父類不說,其他類應(yīng)該有的兩個(gè)方法是condition和action,前者是用來判斷讀進(jìn)來的字符串是不是符合自家規(guī)則,后者是用來執(zhí)行操作的,所謂的執(zhí)行操作就是指調(diào)用“處理程序模塊”,輸出前標(biāo)簽、內(nèi)容、后標(biāo)簽。 來看下這個(gè)模塊的代碼,其實(shí)這個(gè)里面幾個(gè)類的關(guān)系,畫到類圖里面看會(huì)比較清晰。 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
補(bǔ)充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 = []
最后隆重的來看下“語(yǔ)法分析器模塊”,這個(gè)模塊的作用其實(shí)就是協(xié)調(diào)讀入的文本和其他模塊的關(guān)系。在往重點(diǎn)說就是,提供了兩個(gè)存放“規(guī)則”和“過濾器”的列表,這么做的好處就是使得整個(gè)程序的靈活性得到了極大的提高,使得規(guī)則和過濾器變成的熱插拔的方式,當(dāng)然這個(gè)也歸功于前面在寫規(guī)則和過濾器時(shí)每一種類型的規(guī)則(過濾器)都單獨(dú)的寫成了一個(gè)類,而不是用if..else來區(qū)分。 看代碼:
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)
這個(gè)模塊里面的處理思路是,遍歷客戶端(也就是程序執(zhí)行的入口)給插進(jìn)去的所有的規(guī)則和過濾器,來處理讀進(jìn)來的文本。
有一個(gè)細(xì)節(jié)的地方也要說一下,其實(shí)是和前面寫的呼應(yīng)一下,就是在遍歷規(guī)則的時(shí)候通過調(diào)用condition這個(gè)東西來判斷是否符合當(dāng)前規(guī)則。
我覺得這個(gè)程序很像是命令行模式,有空可以復(fù)習(xí)一下該模式,以保持記憶網(wǎng)節(jié)點(diǎn)的牢固性。
最后說一下我以為的這個(gè)程序的用途:
1、用來做代碼高亮分析,如果改寫成js版的話,可以做一個(gè)在線代碼編輯器。
2、可以用來學(xué)習(xí),供我寫博文用。
還有其他的思路,可以留下您的真知灼見。
補(bǔ)充一個(gè)類圖,很簡(jiǎn)陋,但是應(yīng)該能說明之間的關(guān)系。另外我還是建議如果看代碼捋不清關(guān)系最好自己畫圖,自己畫圖才能熟悉整個(gè)結(jié)構(gòu)。
- 手動(dòng)實(shí)現(xiàn)把python項(xiàng)目發(fā)布為exe可執(zhí)行程序過程分享
- python調(diào)用新浪微博API項(xiàng)目實(shí)踐
- Python自動(dòng)化運(yùn)維和部署項(xiàng)目工具Fabric使用實(shí)例
- 對(duì)Python的Django框架中的項(xiàng)目進(jìn)行單元測(cè)試的方法
- Linux下將Python的Django項(xiàng)目部署到Apache服務(wù)器
- 詳解使用Nginx和uWSGI配置Python的web項(xiàng)目的方法
- 把項(xiàng)目從Python2.x移植到Python3.x的經(jīng)驗(yàn)總結(jié)
- Python中SOAP項(xiàng)目的介紹及其在web開發(fā)中的應(yīng)用
- 使用Python實(shí)現(xiàn)一個(gè)簡(jiǎn)單的項(xiàng)目監(jiān)控
- 十個(gè)Python練手的實(shí)戰(zhàn)項(xiàng)目,學(xué)會(huì)這些Python就基本沒問題了(推薦)
相關(guān)文章
Python發(fā)送郵件測(cè)試報(bào)告操作實(shí)例詳解
這篇文章主要介紹了Python發(fā)送郵件測(cè)試報(bào)告操作,結(jié)合實(shí)例形式較為詳細(xì)的分析了Python郵件發(fā)送相關(guān)模塊使用及操作注意事項(xiàng),需要的朋友可以參考下2018-12-12python自定義模塊使用.pth文件實(shí)現(xiàn)重用方式
這篇文章主要介紹了python自定義模塊使用.pth文件實(shí)現(xiàn)重用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-02-02手把手教你怎么用Python實(shí)現(xiàn)zip文件密碼的破解
之前在家里的老電腦中,發(fā)現(xiàn)一個(gè)加密zip壓縮包,由于時(shí)隔太久忘記密碼了,依稀記得密碼是6位字母加數(shù)字,網(wǎng)上下載了很多破解密碼的軟件都沒有效果,于是想到自己用Python寫一個(gè)暴力破解密碼的腳本,需要的朋友可以參考下2021-05-05Python學(xué)習(xí)筆記之變量、自定義函數(shù)用法示例
這篇文章主要介紹了Python學(xué)習(xí)筆記之變量、自定義函數(shù)用法,結(jié)合實(shí)例形式分析了Python變量、自定義函數(shù)的概念、功能、使用方法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2019-05-05python進(jìn)行TCP端口掃描的實(shí)現(xiàn)
這篇文章主要介紹了python進(jìn)行TCP端口掃描的實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-12-12Python運(yùn)行時(shí)修改業(yè)務(wù)SQL代碼
這篇文章主要介紹了Python運(yùn)行時(shí)修改業(yè)務(wù)SQL代碼,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-06-06一篇文章入門Python生態(tài)系統(tǒng)(Python新手入門指導(dǎo))
原文寫于2011年末,雖然文中關(guān)于Python 3的一些說法可以說已經(jīng)不成立了,但是作為一篇面向從其他語(yǔ)言轉(zhuǎn)型到Python的程序員來說,本文對(duì)Python的生態(tài)系統(tǒng)還是做了較為全面的介紹2015-12-12