PYTHON基礎教程中的十個專案(1)

R__phoenix發表於2014-06-05

短斷斷續續學了很久的Python了,一直在看書,沒怎麼敲過程式碼,看到最後面十個專案的時候,第一次看這種專案的程式碼還是很費力的,至少對我是這樣,裡面有挺多構造器的知識還是以後要深入的瞭解,還有就是翻譯過來的書確實有很多都是語言不通的,讀起來,理解起來很費勁。話不多說,我把程式碼貼上,裡面有很詳細的註釋,還有就是敘述一下整個專案的工作流程,我是看了這個專案看了有4,5遍左右才對這個專案有個整體的瞭解。




首先,專案的主程式應該就是parser這個類,也就是語法構造器,專案所有的功能都是以這個檔案中的類為起點進行的。

首先建立一個處理器的物件,因為在執行parser類中的方法時,當決定了規則和過濾器的時候,是要用handler中的物件進行呼叫那些方法的。並且要初始化規則和過濾器的佇列,以便在檢測檔案的時候使用。


建立一個主類的物件parser.parse(sys.stdin)

程式執行的時候會在標準輸入,也就是螢幕接受程式執行所需要的引數,比如要標記檔案的檔名。

然後進入parse方法中執行,每一次利用前面的blocks方法來取文章中的一個塊,然後用過濾器和規則來檢測這段文字,以至於決定到底要呼叫什麼方法,因為規則是和輸出有關的,所以當選定規則之後,這一段文字的標記也就出來了。



markup.py


#coding=utf-8
import sys, re
from handlers import *
from util import *
from rules import *


class Parser:
    """
    整個程式的主類,裡面主要是對文字進行相應的語法分析,然後分別用合適的規則和過濾器處理文字,最後輸出
    """
    def __init__(self, handler):
        """
        初始化程式的處理物件handler以及規則和過濾器儲存陣列
        """
        self.handler = handler  
        self.rules = []
        self.filters = []

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

    def addFilter(self, pattern, name):
        """
        利用filter建立一個過濾器,過濾器就是一個函式handler.sub(name)。
        filters列表每個元素都是一個filter函式,只不過name不同,handler呼叫的方法也就會不同
        """
        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 each_filter in self.filters:
                block = each_filter(block, self.handler)
            for each_rule in self.rules:
                if each_rule.condition(block):
                    last = each_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-zA-Z/]+)', 'url')
        self.addFilter(r'([\.a-zA-Z]+@[\.a-zA-Z]+[a-zA-Z])', 'mail')


handler = HTMLRenderer()
parser = BasicTextParser(handler)
parser.parse(sys.stdin)

handlers.py


#coding=utf-8
class Handler:
	"""
	當從parser中利用handler物件呼叫方法的時候就會使用這個類裡面的函式
	某種意義上說這是整個程式的處理器,由parser發出指令,然後再handler中呼叫
	相應的函式去執行
	"""

	def callback(self, prefix, name, *args):
		"""
		prefix是函式的字首名,name為函式名,args為呼叫這個函式的引數,*args會接受一些冗餘引數
		如果要呼叫的函式存在,那麼就返回這個函式,如果沒有,那麼就自動返回None這也是getattr的作用
		"""
		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):
			"""
			這個函式會被應用在re.sub中的第二個函式引數來使用
			"""
			result = self.callback('sub_', name, match)
			if result is None: result = match.group(0)
			return result
		return substitution

class HTMLRenderer(Handler):


    def start_document(self):
        print "<html><head><title>hahaha</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_email(self, match):
        return '<a href = "mailto:%s">%s</a>' % (match.group(1), match.group(1))

    def feed(self, data):
        print data



rules.py


#coding=utf-8
class Rule:
	"""
	所有規則的父類,因為所有的規則類都有action方法,且呼叫形式幾乎一樣,所以
	在父類中設定一個action函式即可.condition函式用來判斷是不是符合該規則,然後通過type和父類中的action函式,呼叫相應
	的處理函式
	"""

	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.firt = 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 = 1
		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

用來查詢段落的ulity.py



#coding=utf-8
def lines(file):
	for line in file: yield line     #每次返回檔案中的一行
	yield '\n'                     #在檔案的結尾新增一個空行,讓程式順利結束

def blocks(file):
	"""
	程式主要用來收集文字中的塊,然後利用各種辦法把這一個塊加上HTML標記,這個函式的主要用途就是
	收集程式的每一個塊,提供給程式做相應的處理
	"""
	block = []
	for line in lines(file):            #依次遍歷檔案中的每一行
		if line.strip():                #如果不是空行,那麼就要新增到陣列裡,這也就是收集塊的過程 
			block.append(line)
		elif block:									#如果是空行,那麼就要把當前收集的是一個塊的字串全都新增到一個陣列裡面返回,並且把陣列清空
			yield ''.join(block).strip()
			block = [];


效果如圖




相關文章