我有一个生成器功能,可以跟踪我是否在某对事件之间 - a" start"事件和"结束"事件。例如,它可以检查令牌并报告我是否在评论分隔符"/*"
和"*/"
之间(非嵌套)。以下代码有效,但有一个很好的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范围),我仍然想知道它。
答案 0 :(得分:1)
我能想到的唯一简化就是围绕设置/重置inside
重写逻辑:
def tokspan(starttok, endtok, stream):
inside = False
for tok in stream:
inside |= (tok == starttok)
yield (inside, tok)
inside &= (tok != endtok)
这是否使得代码的可读性或多或少都在旁观者眼中。
答案 1 :(得分:0)
可能在这里使用装饰器。我不确定这对你是否有用,但这可能只是给你一些想法。
创建一个装饰器,用于存储您要过滤掉的项目:
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'))
现在您将装饰器应用于接受字符串的函数。这会将函数转换为输入为迭代器的函数。然后像处理任何其他迭代器一样处理迭代器。
当然,你总是可以在任何时候将迭代器转换为字符串(比如在这里):
# 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错 t错 假 x错 ;假 假 /真的 *是的 真正 一个真的 真正 是的 真的 是的 - 是的 是的 真的 真的 真的 我是真的 是的 克。真的 真正 是的 真的 是的 是的 真的 是的 真的 真正 真的 真的 是的 。真正 真正 *错 /错 假 x错 =假 1错 ;假 假 我错了 一个错误 我错了 n错 (错 )错误