用python设计可重用的解析器
我正在编写一个文件解析器,我希望能够确定它将返回给我的“数据字段” 我开始学习python,仍然习惯于像Java程序员一样思考,所以这个问题更多的是关于如何设计我的模块,而不是如何具体解析文件 根据上下文,文件的每一行都有固定数量的字符,并且每个信息都包含在特定索引之间。例如:用python设计可重用的解析器,python,Python,我正在编写一个文件解析器,我希望能够确定它将返回给我的“数据字段” 我开始学习python,仍然习惯于像Java程序员一样思考,所以这个问题更多的是关于如何设计我的模块,而不是如何具体解析文件 根据上下文,文件的每一行都有固定数量的字符,并且每个信息都包含在特定索引之间。例如: XX20120101NAME1CITYA XY20120101NAME2CITYB 在这个虚构的例子中,从索引0到索引2,您有一个信息,从索引2到索引10,依此类推 使用Java,我通常会创建一个表示不同信息片段的枚举
XX20120101NAME1CITYA
XY20120101NAME2CITYB
在这个虚构的例子中,从索引0到索引2,您有一个信息,从索引2到索引10,依此类推
使用Java,我通常会创建一个表示不同信息片段的枚举器,每个“存储”开始索引和结束索引。在我的解析类中,我将提供一个方法来接受n个不同的枚举。例如:
enum FileInformation {
INFO01(0,2), INFO02(2,10), INFO03(10,15), INFO04(15,20);
int startIndex;
int endIndex;
public FileInformation(int si, int ei) {
this.startIndex = si;
this.endIndex = ei;
}
public int getStartIndex() { return si; }
public int getEndIndex() { return ei; }
}
public Whatever parse(FileInformation... infos) {
// Here I would iterate through infos[],
// using its start and end index to retrieve only what I need.
}
我知道我可能不应该在python中使用相同的虽然行,特别是因为该语言不允许使用它(python中没有枚举),并且因为我认为python可以不那么冗长,但我不知道有什么好的设计实践可以达到同样的结果
值得一提的是,我不想让模块的用户暴露在不必要的复杂性之下,也不想强迫他知道每个信息的索引。模块的用户最好能够确定他想要的信息及其顺序
那么,你对优雅地解决这些必要条件有什么见解吗?
提前感谢Python已经有了一个内置类型,它完成了FileInformation所做的事情—请检查 以下是您的模块的外观:
# module dataparser.py
INFO01, INFO02, INFO03, INFO04 = map(slice, ((0,2),(2,10),(10,15),(15,20)))
def parse(infos, data):
return [data[info] for info in infos]
以及调用模块如何使用它:
# module dataparser_user.py
import dataparser as dp
data = """\
XX20120101NAME1CITYA
XY20120101NAME2CITYB""".splitlines()
for d in data:
print d, dp.parse((dp.INFO01, dp.INFO03), d)
# or use partial to define a function object that takes your
# subset number of slices
from functools import partial
specific_parse = partial(dp.parse, (dp.INFO01, dp.INFO03))
for d in data:
print d, specific_parse(d)
如果要在Python中实现自己的enum
模拟,我认为namedtuple
将是最接近的东西(因为Javaenum
有getter,但没有setter-namedtuple
s同样是不可变的):
这非常有帮助。很多有用的信息。。。感谢INFO01,INFO02,INFO03,INFO04=map(slice,((0,2),(2,10),(10,15),(15,20)))我不得不用INFO01,INFO02,INFO03,INFO04=[slice(I[0],I[1]代替我在[(0,2),(2,10),(10,15),(15,20)]啊!那么这也应该起作用:
INFO01,INFO02,INFO03,INFO04,INFO04=[slice(*I)代替[(0,2),(2,10),(10,15),(15,20)]
“*”告诉Python将每个元组i
解压为slice
的参数。对于命名的元组,可能也需要同样的技巧。
from collections import namedtuple
FileInformation = namedtuple("FileInformation", "start end")
INFO01, INFO02, INFO03, INFO04 = map(FileInformation, ((0,2),(2,10),(10,15),(15,20)))