simple_markup.py

 import sys, re
from util import * print('<html><head><title>...</title><body>') title = True
for block in blocks(sys.stdin):
block = re.sub(r'\*(.+?)\*',r'<em>\1</em>',block)
if title:
print('<h1>')
print(block)
print('</h1>')
title = False
else:
print('<p>')
print(block)
print('</p>') print('</body></html>')

handler_first.py

 class Handler:
"""
处理从Parser调用的方法的对象。 这个解析器会在每个块的开始部分调用start()和end()方法,使用合适的块作为参数。
sub()方法会作用于正则表达式的替换中。当使用了'emphasis'这样的名字调用时,它会
返回合适的替换函数。
"""
def callback(self, prefix, name, *args):
method = getattr(self, prefix+name, None)
if callable(method): return method(*args)

handler.py

 class Handler:
"""
处理从Parser调用的方法的对象。 这个解析器会在每个块的开始部分调用start()和end()方法,使适用合适的
块名作为参数。sub()方法会用于正则表达式替换中。当使用了'emphasis'
这样的名字调用时,它会返回合适的替换函数。
"""
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:result= match.group(0)
return result
return substitution class HTMLRenderer(Handler):
"""
用于生成HTML的具体处理程序 HTMLRenderer内的方法都可以通过超类处理程序的start()、
end()和sub()方法来访问。它们实现了用于HTML文档的基本标签。
"""
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_email(self, match):
return '<a href="mailto:%s">%s</a>' % (match.group(1), match.group(1))
def feed(self, data):
print(data)

markup.py

 import sys, re
from handlers import *
from util import *
from rules import * class Parser:
"""
语法分析器读取文本文件、应用规则并且控制处理器程序
""" # 初始化成员,handler,rules(),filters()
def __init__(self, handler):
self.handler = handler
self.rules = []
self.filters = [] # 添加rule,方便扩展
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) # 方法parse,读取文本(调用util.py的blocks(file))并分成block,
# 使用循环用规则(rule)和过滤器(filter(block, handler)处理block,
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):
if rule.action(block,self.handler):break self.handler.end('document') # Parser派生出的具体的类(通过添加具体的规则和过滤器):用于添加HTML标记 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实例,构造parser(使用对应的handler)实例,调用parser的方法parser进行对文本的处理
handler = HTMLRenderer()
parser = BasicTextParser(handler) parser.parse(sys.stdin)

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):
"""
A heading is a single line that is at most 70 characters and
that doesn't end with a colon.
"""
type = 'heading' def condition(self, block):
return not '\n' in block and len(block) <= 70 and not block[-1] == ':' class TitleRule(HeadingRule):
"""
The title is the first block in the document, provided that
it is a heading.
"""
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):
"""
A list item is a paragraph that begins with a hyphen. As part of the
formatting, the hyphen is removed.
"""
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):
"""
A list begins between a block that is not a list item and a
subsequent list item. It ends after the last consecutive list item.
"""
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):
"""
A paragraph is simply a block that isn't covered by any of the other rules.
"""
type = 'paragraph' def condition(self, block):
return True

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=[]#新生成一个空列表,继续以上的步骤

test_input.py

 Welcome to World Wide Spam, Inc.

 These are the corporate web pages of *World Wide Spam*, Inc. We hope
you find your stay enjoyable, and that you will sample many of our
products. A short history of the company World Wide Spam was started in the summer of 2000. The business
concept was to ride the dot-com wave and to make money both through
bulk email and by selling canned meat online. After receiving several complaints from customers who weren't
satisfied by their bulk email, World Wide Spam altered their profile,
and focused 100% on canned goods. Today, they rank as the world's
13,892nd online supplier of SPAM. Destinations From this page you may visit several of our interesting web pages: - What is SPAM? (http://wwspam.fu/whatisspam) - How do they make it? (http://wwspam.fu/howtomakeit) - Why should I eat it? (http://wwspam.fu/whyeatit) How to get in touch with us You can get in touch with us in *many* ways: By phone(555-1234), by
email (wwspam@wwspam.fu) or by visiting our customer feedback page
(http://wwspam.fu/feedback).

test_output.py

 <html><head><title>...</title></head><body>
<h1>
Welcome to World Wide Spam, Inc.
</h1>
<p>
These are the corporate web pages of <em>World Wide Spam</em>, Inc. We hope
you find your stay enjoyable, and that you will sample many of our
products.
</p>
<h2>
A short history of the company
</h2>
<p>
World Wide Spam was started in the summer of 2000. The business
concept was to ride the dot-com wave and to make money both through
bulk email and by selling canned meat online.
</p>
<p>
After receiving several complaints from customers who weren't
satisfied by their bulk email, World Wide Spam altered their profile,
and focused 100% on canned goods. Today, they rank as the world's
13,892nd online supplier of SPAM.
</p>
<h2>
Destinations
</h2>
<p>
From this page you may visit several of our interesting web pages:
</p>
<ul>
<li>
What is SPAM? (<a href="http://wwspam.fu/whatisspam">http://wwspam.fu/whatisspam</a>)
</li>
<li>
How do they make it? (<a href="http://wwspam.fu/howtomakeit">http://wwspam.fu/howtomakeit</a>)
</li>
<li>
Why should I eat it? (<a href="http://wwspam.fu/whyeatit">http://wwspam.fu/whyeatit</a>)
</li>
</ul>
<h2>
How to get in touch with us
</h2>
<p>
You can get in touch with us in <em>many</em> ways: By phone(555-1234), by
email (wwspam@wwspam.fu) or by visiting our customer feedback page
(<a href="http://wwspam.fu/feedback">http://wwspam.fu/feedback</a>).
</p>
</body></html>

readme.txt

 20.1 问题是什么
将文本由程序自动转成HTML 要做的工作基本上就是首先将各种文本元素进行分类,比如标题和被强调的文本,然后清晰地标记出它们。为此,
要将HTML标记添加到文本中,使文档能在浏览器中作为网页显示并使用。 编写原型 定义目标 输入不应该包含人工代码或者标签
应该可以处理不同的块
20.2 有用的工具
要对文件能读写,或者至少能从标准输入(sys.stdin)中读写,在print输出
需要对所输入的行进行迭代
需要使用一些字符串方法
需要一个或者两个生成器
可能需要用到re模块
20.3 准备工作
测试套件评估进度 test_input.txt
20.4 初次实现
首先要做的是本文本切成段落,段落被一个或者多个空行隔开。比段落更准确的是块(block)
20.4.1 找出文本块
找出块的简单方法就是搜集遇到的行,直到遇到一个空行,然后返回已经收集到的行。那些返回的行就是一个块。
if 。。elif的逻辑选择,
20.5.2 添加一些标记 总结:
主程序(markup.py)
1、将处理过程封装为方法parse,这个整个程序的处理过程
2、将规则条件抽象成规则类,避免了大量if语句使用。
3、self.addRule增加规则对象。利用规则对象的方法和属性实际操作块的处理。
4、生成一个html处理器对象(HTMLRenderer),传给BasicTextParser生成对象parser,改该对象调用rule对象接受handler
对象处理block
5、最重要的是如何将功能抽象成具体的类,以及各个类所有的功能,高内聚低耦合。

fun_study.py

 # def count():
# '''
# 创建以一个空列表,每次讲定义的函数名存入列表,函数执行三次,列表值[f,f,f]
# 第三次时i为3,fi()=f(),这是f同样保存了,第三次时的父函数的作用域i=3
# 所以f1=3*3=9
# '''
# fs = []
# for i in range(1, 4):
# def f():
# return i*i
# fs.append(f)
# print(i)
# return fs def count():
def f(j):
def g():
return j*j
return g
fs = []
for i in range(1, 4):
fs.append(f(i))
return fs
'''体现闭包的用法。fs中函数对象将f(1),f(2),f(3)作用域存放在函数中'''
f1,f2,f3=count()
print(f1())
print(f2())
print(f3())

python基础教程2第20章 项目1:即时标记的更多相关文章

  1. 《Python基础教程》第20章学习笔记

    python实现:https://github.com/captainwong/instant_markup c++实现:https://github.com/captainwong/instant_ ...

  2. 《Python基础教程》第2章读书笔记(1)

    # -*- coding:utf-8 -*- #最基本的数据结构:序列,索引从0开始 #python包括6种内建的序列 #最常用的序列包括:列表,元祖 #列表 edward = ['Edward Gu ...

  3. python基础教程第二版 第一章

    1.模块导入python以增强其功能的扩展:三种方式实现 (1). >>> Import math >>> math.floor(32.9) 32.0 #按照 模块 ...

  4. Python基础教程笔记——第7章:更加抽象(类)

    下面进入Python的面向对象: 对象的魔力: 多态:---可以对不同类的对象使用同样的操作 封装:---对外部隐藏对象内部的工作方式 继承:---以普通的类为基础建立专门的类对象 (1)多态: is ...

  5. Python基础教程笔记——第4章:字典

    字典 字典是Python唯一内建的数学映射类型,字典中的值没有特殊的顺序,键可以是数字,字符串,甚至是元组 字典的创建: 字典由键值对构成,字典中键是唯一的,而值不唯一.>>> a_ ...

  6. Python基础教程笔记——第2章:列表和元组

    python shell 里重复上一次的命令:Alt+p 2.3 列表:Python的苦力 (1)list函数 (2)列表赋值,不蹦蹦为一个元素不存在的位置赋值 (3)删除元素,del name[1] ...

  7. Python基础教程笔记——第1章

    1.8 函数 pow(x,y) x^y abs(x)          取数的绝对值 round(x)   会把浮点数四舍五入为最接近的整数 floor(x)     向下取整的函数,但是需要先imp ...

  8. 《Python基础教程》第五章:条件、循环和其他语句

    在Python中赋值运算和比较运算是可以连接的,运算符可以连在一起使用,如:0<age<100 ==运算符判定两个对象是否相等,is判定两者是否等同(同一个对象) 断言,在错误条件出现时直 ...

  9. 《Python基础教程》第1章读书笔记

    # -*- coding:utf-8 -*- x = "hello " y = "world" print x+y print "hello &quo ...

随机推荐

  1. Mac下homebrew的安装与卸载

    mac系统常用的软件安装工具就是homebrew 个人认为通过brew安装比较简单,下面介绍下如何安装 安装和卸载homebrew 安装 /usr/bin/ruby -e "$(curl - ...

  2. redis实现分布式锁需要考虑的因素以及可重入锁实现

    死锁 错误例子 解决方式  防止死锁 通过设置超时时间  不要使用setnx key   expire 20  不能保证原子性 如果setnx程序就挂了 没有执行expire就死锁了  reidis2 ...

  3. CFgym100020 Problem J. Uprtof

    题意:给你n个点m无向条边.每个点是黑色或者白色的.m条边第一条边边权为2^m,第二条边边权为2^(m-1)....... .在这个图上选择一些边连起来,使得满足:每个黑点连奇数条边,每个白点连偶数条 ...

  4. 安卓8.0真机运行appium1.4遇到的问题:运行自动化脚本,手机自动安装 settings.apk和unclock.apk,执行脚本时提示安装UnicodeIME-debug.apk失败,怎么关掉自动安装?

    运行自动化脚本,手机自动安装 settings.apk和unclock.apk,执行脚本时提示安装UnicodeIME-debug.apk失败,怎么关掉自动安装? 这3个apk的目录分别是: D:\P ...

  5. redis相关笔记(一.安装及单机及哨兵使用)

    redis笔记一 redis笔记二 redis笔记三 1.安装 cd /usr/src #进入下载目录(这个目录自己定) yum install -y wget gcc make tcl #安装依赖 ...

  6. JZOJ4605. 排序(线段树合并与分裂)

    题目大意: 每次把一个区间升序或降序排序,最后问一个点是什么. 题解: 如果只是问一个点,这确乎是个经典题,二分一下答案然后线段树维护01排序. 从pty那里get到了可以用线段树的合并与分裂实时地维 ...

  7. 「CTS2019 | CTSC2019」氪金手游 解题报告

    「CTS2019 | CTSC2019」氪金手游 降 智 好 题 ... 考场上签到失败了,没想容斥就只打了20分暴力... 考虑一个事情,你抽中一个度为0的点,相当于把这个点删掉了(当然你也只能抽中 ...

  8. 数字三角形W(加强版) codevs 2189

    2189 数字三角形W 时间限制: 1 s 空间限制: 32000 KB 题目等级 : 黄金 Gold 题目描述 Description 数字三角形 要求走到最后mod 100最大 输入描述 Inpu ...

  9. 谈html mailto(电子邮件)实际应用

    大家知道,mailto是网页设计制作中的一个非常实用的html标签,许多拥有个人网页的朋友都喜欢在网站的醒目位置处写上自己的电子邮件地址,当点击时就能自动打开当前计算机系统中默认的电子邮件客户端软件, ...

  10. Bochs调试VirtualBox生成的VDI映像

    将VDI映像转换成Bochs支持的img映像 1: vboxmanage clonehd source.vdi destination.img --format RAW 在bochsrc.txt中引用 ...