Fortran 列表定向输入的 Python 等价物

标签 python format fortran ascii

我希望能够从 Python 中的输入文件中读取数据,类似于 Fortran 处理列表定向读取的方式(即 read (file, *) char_var, float_var, int_var).

棘手的部分是,就输入格式而言,Fortran 处理读取语句的方式非常“宽容”。例如,使用前面的语句,这个:

"some string" 10.0, 5

将被解读为:

"some string",      10.0
5

还有这个:

"other string", 15.0 /

读作相同:

"other string"
15
/

int_var 的值保持与读取语句之前相同的值。更棘手的是:

"nother string", , 7

会将值分配给 char_varint_varfloat_var 保留与读取语句之前相同的值。

有没有一种优雅的方式来实现这个?

最佳答案

这确实很棘手 - 我发现编写一个基于纯 python 状态的分词器比考虑一个正则表达式来解析每一行更容易(虽然这是可能的)。

我用过 link provided by Vladimir作为规范 - 分词器有一些通过的文档测试。

def tokenize(line, separator=',', whitespace="\t\n\x20", quote='"'):
    """
    >>> tokenize('"some string" 10.0, 5')
    ['some string', '10.0', '5']

    >>> tokenize(' "other string", 15.0 /')
    ['other string', '15.0', '/']

    >>> tokenize('"nother string", , 7')
    ['nother string', '', '7']

    """
    inside_str = False
    token_started = False
    token = ""
    tokens = []
    separated = False
    just_added = False
    for char in line:
        if char in quote:
            if not inside_str:
                inside_str = True

            else:
                inside_str = False
                tokens.append(token)
                token = ""
                just_added = True
            continue
        if char in (whitespace + separator) and not inside_str:
            if token:
                tokens.append(token)
                token = ""
                just_added = True
            elif char in separator:
                if not just_added:
                    tokens.append("")
                just_added = False
            continue
        token += char
    if token:
        tokens.append(token)
    return tokens


class Character(object):
    def __init__(self, length=None):
        self.length = length
    def __call__(self, text):
        if self.length is None:
            return text
        if len(text) > self.length:
            return text[:self.length]
        return "{{:{}}}".format(self.length).format(text)


def make_types(types, default_value):
    return types, [default_value] * len[types]


def fortran_reader(file, types, default_char="/", default_value=None, **kw):
    types, results = make_types(types, default_value)
    tokens = []
    while True:
        tokens = []
        while len(tokens) < len(results):
            try:
                line = next(file)
            except StopIteration:
                raise StopIteration
            tokens += tokenize(line, **kw)
        for i, (type_, token) in enumerate(zip(types, tokens)):
            if not token or token in default_char:
                continue
            results[i] = type_(token)
        changed_types = yield(results)
        if changed_types:
            types, results = make_types(changed_types)

我没有深思熟虑地测试这个 - 但对于分词器 - 它被设计为在 Python for 语句中工作,如果相同的字段一遍又一遍地重复 - 或者它可以与 Python 的迭代器 send 方法一起使用以将值更改为在每次迭代中被读取。

请测试,并将一些测试文件通过电子邮件发送给我(地址在我的个人资料中)。如果确实没有任何相似之处,也许这值得一些润色并在 Pypi 中发布。

关于Fortran 列表定向输入的 Python 等价物,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36165050/

相关文章:

python - 从元组列表中删除部分重复的元组

python - 检查python中networkx中是否存在具有相同标签的节点

c++ - ctypes/C++ 段错误访问成员变量

python - 如何防止 Python 返回到 C++ boost::python::error_already_set?

php - 数据库中的日期格式与输出不同

Fortran:将 double 复数转换为单精度

Java奇怪的字符串间距问题

linux - 在 Linux 系统调用 write() 上使用格式说明符

c++ - 当 C 代码调用 Fortran 子程序时,子程序顶部发生段错误

preprocessor - 在 cpp 中截断字符串(预处理器)