这是《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
这个程序堪称是整个“项目”的基石所在:提供了标签的输出,以及字符串的替换。理解起来也比较简单。
再来看第二个模块“过滤器”,这个模块更为简单,其实就是一个正则表达式的字符串。相关代码如下:
代码如下:
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牌过滤器。熟悉正则表达式的同学理解起来是没有压力的。
再来看第三个模块“规则”,这个模块,抛开那祖父类不说,其他类应该有的两个方法是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)