扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
作者:Boudewijn Rempt、David Mertz 来源:code173.com 2007年9月15日
关键字: 软件
处理 .INI 文件的分块 Python 代码
import string txt = open('hypothetical.ini').read() sects = string.split(txt, '[') for sect in sects: # do something with sect, like get its name # (the stuff up to ']') and read its assignments |
或者,如果愿意,可以使用单个 current_section
变量来确定位置:
处理 .INI 文件的计算 Python 代码
for line in open('hypothetical.ini').readlines(): if line[0] == '[': current_section = line(1:-2) elif line[0] == ';': pass # ignore comments else: apply_value(current_section, line) |
何时使用状态机
现在,我们已经决定了如果文本文件“太简单”就不使用状态机,让我们再研究 需要使用状态机的情况。本专栏中讨论了实用程序 Txt2Html,它将“智能 ASCII”(包括本文)转换成 HTML。让我们扼要重述。
“智能 ASCII”是一种文本格式,它使用一些间隔约定来区分文本块的类型,如头、常规文本、引语和代码样本。虽然读者或作者能容易地通过查看分析这些文本块类型之间的转移,但却没有简单的方法可以让计算机将“智能 ASCII”文件分割成组成它的文本块。不像 .ini 文件示例,文本块类型可以任何顺序出现。在任何情况下都没有单一定界符来分隔块(空行 通常分隔文本块,但代码样本中的空行却不一定结束代码样本,并且文本块不需要用空行来分隔)。由于需要以不同方式重新格式化每个文本块以生成正确的 HTML 输出,状态机似乎就是自然的解决方案。
Txt2Html 阅读器的一般功能如下:
这个例子是关于您会遇到的最简单的情况,但它说明了我们描述过的以下模式:
Python 中一个简单的状态机输入循环
global state, blocks, bl_num, newblock #-- Initialize the globals state = "HEADER" blocks = [""] bl_num = 0 newblock = 1 for line in fhin.readlines(): if state == "HEADER": # blank line means new block of header if blankln.match(line): newblock = 1 elif textln.match(line): startText(line) elif codeln.match(line): startCode(line) else: if newblock: startHead(line) else: blocks[bl_num] = blocks[bl_num] + line elif state == "TEXT": # blank line means new block of text if blankln.match(line): newblock = 1 elif headln.match(line): startHead(line) elif codeln.match(line): startCode(line) else: if newblock: startText(line) else: blocks[bl_num] = blocks[bl_num] + line elif state == "CODE": # blank line does not change state if blankln.match(line): blocks[bl_num] = blocks[bl_num] + line elif headln.match(line): startHead(line) elif textln.match(line): startText(line) else: blocks[bl_num] = blocks[bl_num] + line else: raise ValueError, "unexpected input block state: "+state |
可以用 Txt2Html 下载从中取出该代码的源文件。请注意:变量 state
声明为 global
,在函数(如 startText()
)中更改它的值。转移条件,如 textln.match()
,是规则表达式模式,但它们可能也是定制函数。实际上,以后会在程序中执行格式化。状态机只将文本文件分析成 blocks
列表中带标签的块。
抽象状态机类
在表单和函数中使用 Python 实现抽象状态机很容易。这使程序的状态机模型比前一个例子中的简单条件块显得更突出(初看,其中的条件与其它条件没有什么不同)。而且,以下类及其关联处理程序在隔离状态中操作方面完成得很好。许多情况下,这改善了封装和可读性。
文件:statemachine.py
StateMachine类实际上正是抽象状态机所需要的。因为使用 Python 传递函数对象是如此简单,与其它语言中的相似类比较,这个类所需使用行数非常少。
要真正使用StateMachine类,需要为每个要使用的状态创建一些处理程序。处理程序必须符合模式。它循环处理事件,直到要转移到另一个状态,此时处理程序应该将一个字节组(它包括新状态名称以及新的状态处理程序需要的任何 cargo)传递回去。
在 StateMachine
类中将 cargo
用作变量的做法将封装状态处理程序所需的数据(该状态处理程序不必调用它的 cargo
变量)。状态处理程序使用 cargo
来传递下一个处理程序所需的内容,于是新的处理程序可以接管前一个处理程序的遗留工作。 cargo
通常包括文件句柄,它允许下一个处理程序可以在前一个处理程序停止后读取更多数据。 cargo
还可能是数据库连接、复杂的类实例或带有几个项的列表。
现在,让我们研究测试样本。在本例中(在以下代码示例中概述),cargo 只是不断将反馈传送给迭代函数的一个数字。只要 val
处于某个范围内,则 val
的下一个值永远只是 math_func(val)
。一旦函数返回了超出范围的值,那么该值将传送到另一个处理程序,或者状态机在调用了一个什么也不做的终态处理程序后就退出。示例说明了一件事: 事件不必是输入事件。它也可以是计算事件(这种情况很少)。状态处理程序相互之间的区别只是在输出它们处理的事件时使用不同的标记。该函数比较简单,没必要使用状态机。但它很好地说明了概念。代码也许比解释更易于理解!
文件:statemachine_test.py
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者