python的即时标记项目练习笔记


Posted in Python onSeptember 18, 2014

这是《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 '<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

这个程序堪称是整个“项目”的基石所在:提供了标签的输出,以及字符串的替换。理解起来也比较简单。

再来看第二个模块“过滤器”,这个模块更为简单,其实就是一个正则表达式的字符串。相关代码如下:

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) <= 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、可以用来学习,供我写博文用。

还有其他的思路,可以留下您的真知灼见。
补充一个类图,很简陋,但是应该能说明之间的关系。另外我还是建议如果看代码捋不清关系最好自己画图,自己画图才能熟悉整个结构。

python的即时标记项目练习笔记

Python 相关文章推荐
使用Python获取CPU、内存和硬盘等windowns系统信息的2个例子
Apr 15 Python
浅谈python配置与使用OpenCV踩的一些坑
Apr 02 Python
python3 面向对象__类的内置属性与方法的实例代码
Nov 09 Python
python 搭建简单的http server,可直接post文件的实例
Jan 03 Python
Python直接赋值、浅拷贝与深度拷贝实例分析
Jun 18 Python
Python生成指定数量的优惠码实操内容
Jun 18 Python
python开发之anaconda以及win7下安装gensim的方法
Jul 05 Python
python config文件的读写操作示例
Sep 27 Python
Python time库基本使用方法分析
Dec 13 Python
Anaconda+VSCode配置tensorflow开发环境的教程详解
Mar 30 Python
python可迭代对象去重实例
May 15 Python
python绘制分布折线图的示例
Sep 24 Python
python脚本实现分析dns日志并对受访域名排行
Sep 18 #Python
python中的字典详细介绍
Sep 18 #Python
python中执行shell命令的几个方法小结
Sep 18 #Python
python处理PHP数组文本文件实例
Sep 18 #Python
Python threading多线程编程实例
Sep 18 #Python
Python中捕捉详细异常信息的代码示例
Sep 18 #Python
python字符串连接的N种方式总结
Sep 17 #Python
You might like
学习php设计模式 php实现命令模式(command)
2015/12/08 PHP
JavaScript CSS修改学习第六章 拖拽
2010/02/19 Javascript
HTML Dom与Css控制方法
2010/10/25 Javascript
jquery mobile实现拨打电话功能的几种方法
2013/08/05 Javascript
如何设置iframe高度自适应在跨域情况下的可用方法
2013/09/06 Javascript
jquery日历控件实现方法分享
2014/03/07 Javascript
jQuery实现提交按钮点击后变成正在处理字样并禁止点击的方法
2015/03/24 Javascript
JavaScript中split与join函数的进阶使用技巧
2016/05/03 Javascript
Jquery中map函数的用法
2016/06/03 Javascript
整理关于Bootstrap列表组的慕课笔记
2017/03/29 Javascript
微信小程序 es6-promise.js封装请求与处理异步进程
2017/06/12 Javascript
Canvas放置反弹效果随机图形(实例)
2017/08/17 Javascript
angular4应用中输入的最小值和最大值的方法
2019/05/17 Javascript
[51:06]2018DOTA2亚洲邀请赛3月29日 小组赛A组 KG VS Liquid
2018/03/30 DOTA
[01:07:21]NAVI vs VG Supermajor 败者组 BO3 第二场 6.5
2018/06/06 DOTA
Python批量重命名同一文件夹下文件的方法
2015/05/25 Python
python类的方法属性与方法属性的动态绑定代码详解
2017/12/27 Python
python得到电脑的开机时间方法
2018/10/15 Python
Python+Pyqt实现简单GUI电子时钟
2021/02/22 Python
Python学习笔记之字符串和字符串方法实例详解
2019/08/22 Python
python中的RSA加密与解密实例解析
2019/11/18 Python
利用keras使用神经网络预测销量操作
2020/07/07 Python
python matplotlib库的基本使用
2020/09/23 Python
python实现粒子群算法
2020/10/15 Python
python3通过subprocess模块调用脚本并和脚本交互的操作
2020/12/05 Python
CSS3实现的闪烁跳跃进度条示例(附源码)
2013/08/19 HTML / CSS
Sony C++笔试题
2013/03/10 面试题
会计学财务管理专业个人的自我评价
2013/10/19 职场文书
医药专业推荐信
2013/11/15 职场文书
儿子婚宴答谢词
2014/01/09 职场文书
歌唱比赛获奖感言
2014/01/21 职场文书
五水共治一句话承诺
2014/05/30 职场文书
2014年平安建设工作总结
2014/11/19 职场文书
2014年公路养护工作总结
2014/12/04 职场文书
一篇合格的广告文案,其主要目的是什么?
2019/07/12 职场文书
CSS+HTML 实现顶部导航栏功能
2021/08/30 HTML / CSS