执行此操作的最简单方法是简单地逐行扫描文件并在找到匹配的行时添加语句。
以下代码可以满足您的需求,但它根本不可靠:
def add_info_on_loops(iterable):
in_loop = False
for line in iterable:
if not in_loop:
if line.startswith('for ') or line.startswith('while '):
in_loop = True
yield 'count = 0\n'
yield 'print "Entry of loop"\n'
yield line
yield ' print "Iteration Number:", count'
yield ' count += 1\n'
else:
yield line
else:
if not line.startswith(' '):
in_loop = False
yield 'print "Exit of loop"\n'
yield line
用法:
>>> code = StringIO("""[code Starts]
... .
... .
... .
... while [condition]:
... [statements]
... [statements]
... [statements]
...
... .
... .
... .
... [code ends]""")
>>> print ''.join(add_info_on_loops(code))
[code Starts]
.
.
.
count = 0
print "Entry of loop"
while [condition]:
print "Iteration Number:", count count += 1
[statements]
[statements]
[statements]
print "Exit of loop"
.
.
.
[code ends]
代码的陷阱:
- 该代码仅处理顶层的循环。类似的东西
if condition: for x in a: ...
无法识别。这可以解决在检查我们是否有循环之前剥离空白行(但您必须考虑不同级别的缩进等)
- 只要循环中有一行没有缩进,代码就会中断。例如,如果您用空行“拆分”代码并且 IDE 去除了空白,就会发生这种情况。一个解决方案可能是等待非空白、非缩进的行而不是非缩进的行。
- 该代码不处理用于缩进的制表符(很容易修复)
- 该代码不处理单行循环(例如
for x in a: print x
)。在这种情况下,您将获得错误的输出。轻松修复检查:
.
count
如果要添加对嵌套循环的支持,使用单个变量会很麻烦。您可能应该在某处有一个整数 id 并使用变量名称,例如count_0
,count_1
每次找到新循环时,id 都会增加。
- 该代码不处理带有括号且键盘上没有空格的表达式。eg
for(a,b) in x:
不被检测为循环,whilefor (a,b) in x:
被检测到。这很容易解决。首先检查该行是否以 and 开头,for
并且while
下一个字符不能是字母、数字、下划线(实际上在 python3 中你也可以使用 unicode 字符,这变得更难测试,但可能)。
- 该代码不处理以缩进循环行结尾的源代码。例如不会添加
for x in a: indented_last_line_of_code()
出口。(很容易修复在函数外部添加检查以查看我们是否有这种情况)。print
in_loop
for
正如您所看到的,编写一段执行您所要求的代码并不是那么简单。我相信你能做的最好的就是使用ast
解析代码然后访问树并在正确的位置添加节点,然后重新访问代码并生成python源代码(通常节点在源代码的行上有指示代码,它允许您复制粘贴完全相同的代码)。