python十个项目之----即时标记

好高兴,终于作出了自己第一个简单的python小项目。下面我来说说自己的收获和体会

首先是util.py

 

def lines(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 = []


util.py很好理解看看下面的三个主要模块:

 

 

 

先来看看处理程序handles.py的部分程序

在上面程序中只有getattr(),callable()函数可能有人感觉陌生。getattr()是判断是否存在函数有打印地址否则为None,callable()函数判断能否被调用。

 

class Handler:
    def callback(self, prefix, name, *args):
        method = getattr(self, prefix + name, None)
        if callable(method): return method(*args)    #callable()
    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: result = 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_titl(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

 

 

 

 

 

上面的handles.py中start()和end()函数用标记html,sub()函数用于匹配。这两个类不复杂,下面在看看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


这个rules.py中是关于如何分类,把具体模块分到某个类去处理。依据类中的condition(),action()处理。其中condition()判断条件是否符合,action()采取行动。在这个paragraph中把其他类处理不了的文字模块处理掉。下面让我们看看主程序markup.py

 

 

import sys, re
from handles 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 BasicTextParse(Parser):
    def __init__(self, handle):
        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 = BasicTextParse(handler)

parser.parse(sys.stdin)


在这个个主程序模块中,parse()函数起着决定性的作用,让我们好好分析一下其中的函数语法:

 

首先是for filter in self.filters:这个循环的意图

是为了和上图正则表达式联合在一起。主要是:一个是强调内容,一个是URL,一个是电子邮件地址。

而for rule in self.rules:中是依据条件判断每个文字模块搭配哪个html。如果condition()函数为真则调用相应的action()函数,若是搭配上了则break。这就保证了一个文字模块只能和一个condition()和action()搭配

我的体会和感触

 

当我做这个程序时遇到一个问题就是每次标题打印两遍(一个是很大的标题,另一个却很小),检测程序的时候才发现HeadingRule和Paragraph类被调用了两遍,感觉明明程序没错啊。。。纠结了好久,最后才发现超类Rule里面的action()函数丢了return True。改正后运行正确了

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值