跟踪序列中的开/关状态

2024-09-30 08:22:42 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个生成器函数,它跟踪我是否处于某对事件之间--一个“开始”事件和一个“结束”事件。例如,它可以检查标记并报告我是否在注释分隔符"/*""*/"(非嵌套)之间。下面的代码可以工作,但是有没有一个很好的itertools组合或逻辑重组来简化它(和/或使它更“pythonic”)呢?你知道吗

def tokspan(starttok, endtok, stream):
    inside = False
    for tok in stream:
        if (not inside) and tok == starttok:
            inside = True
        yield (inside, tok)
        if inside and tok == endtok:
            inside = False          

tstream = "int x; /* a non-nesting comment /* etc. */ x=1; main();".split()          
for status, tok in tokspan("/*", "*/", tstream):
    print(status, tok)

上面(有意地)为边界标记(/**/)返回True,但这并不特别重要。如果您有一种方法碰巧排除了一个或两个边界(就像python范围那样),我仍然想知道它。你知道吗


Tags: andin标记falsetrueforstreamif
2条回答

我能想到的唯一简化是重写设置/重置inside的逻辑:

def tokspan(starttok, endtok, stream):
    inside = False
    for tok in stream:
        inside |= (tok == starttok)
        yield (inside, tok)
        inside &= (tok != endtok)

这是否使代码可读性增加或减少,是旁观者的眼中钉。你知道吗

也许可以在这里用一个装饰工。我不确定这是否会对你有用,但这可能只是给你一些想法。你知道吗

创建一个decorator,用于存储要过滤的项:

import itertools as it

class insideDec(object):

    def __init__(self, start, stop):

        self.start = start
        self.stop  = stop

    def __call__(self, f):

        def wrapper(x):
            x1 = it.dropwhile(lambda m: not m.startswith(self.start), x  )
            x1.next()
            x2 = it.takewhile(lambda m: not m.startswith(self.stop),  x1 )
            return f(x2)

        return wrapper 

@insideDec('{', '}')
def f(val):
    return val

if __name__ == '__main__':
    print ''.join(f('This is some {string that needs to} be printed'))

现在将decorator应用于接受字符串的函数。这将把函数转换成一个以迭代器为输入的函数。然后像处理其他迭代器一样处理迭代器。你知道吗

当然,您可以随时将迭代器转换为字符串(例如这里):

        # rest of the code ...
        x2 = it.takewhile(lambda m: not m.startswith(self.stop),  x1 )
        return f(''.join(x2))
        # rest of the code ...

这真的取决于你。。。你知道吗

编辑:

很抱歉。我误解了你的问题。对于标记化,下面的内容可能会有所帮助?你知道吗

class tokenize():

    def __init__(self, strVal, start, stop):
        self.start   = start
        self.stop    = stop
        self.strTees = it.tee(strVal, len(start))
        self.inside  = False
        for i, strTee in enumerate(self.strTees):
            for j in range(i):
                next(strTee, '')
        self.strVals = it.izip( *self.strTees )

    def __iter__(self):
        return self

    def next(self):

        v = ''.join(self.strVals.next())
        if v == '': raise StopIteration
        if v == self.start: self.inside = True
        if v == self.stop:  self.inside = False

        # print '[',v, ']'

        return (v[0], self.inside)


if __name__ == '__main__':

    strVal = 'int x; /* a non-nesting comment etc. */ x=1; main();'
    for x, y in tokenize( strVal, '/*', '*/' ):
        print x, y

再说一次,这不是完美的,也许可以达到你的目的。。。你知道吗

以下是输出: 我错了 n错误 不是假的 假 x错误 ;错误 假 /是的 *是的 是的 真实的 是的 n正确 哦,是的 n正确 -是的 n正确 是的 这是真的 不是真的 我是真的 n正确 g正确 是的 c正确 哦,是的 我是真的 我是真的 是的 n正确 不是真的 是的 是的 不是真的 c正确 . 是的 是的 *假 /假 假 x错误 =错误 1个错误 ;错误 假 我错了 假的 我错了 n错误 (错误) )假

相关问题 更多 >

    热门问题