我决定尝试在将函数文本编译成字节码并执行之后对其进行预处理。这只是为了训练。我很难想象它会成为一个令人满意的解决方案的情况。我遇到了一个我想以这种方式解决的问题,但最终找到了更好的方法。所以这只是为了训练和学习新东西,而不是为了真正的使用。
假设我们有一个函数,我们希望在编译之前对源代码进行大量修改:
def f():
1;a()
print('Some statements 1')
1;a()
print('Some statements 2')
例如,让其中的一些行用 标记1;
,以便它们有时被注释,有时不被注释。我只是举个例子,功能的修改可能会有所不同。
为了评论这些行,我做了一个装饰器。整个代码如下:
from __future__ import print_function
def a():
print('a()')
def comment_1(s):
lines = s.split('\n')
return '\n'.join(line.replace(';','#;',1) if line.strip().startswith('1;') else line for line in lines)
def remove_1(f):
import inspect
source = inspect.getsource(f)
new_source = comment_1(source)
with open('temp.py','w') as file:
file.write(new_source)
from temp import f as f_new
return f_new
def f():
1;a()
print('Some statements 1')
1;a()
print('Some statements 2')
f = remove_1(f) #If decorator @remove is used above f(), inspect.getsource includes @remove inside the code.
f()
我使用了 inspect.getsourcelines来检索函数f
代码。然后我进行了一些文本处理(在这种情况下,注释行以 开头1;
)。之后我将它保存到temp.py
模块,然后导入。f
然后在主模块中装饰一个函数。
应用装饰器时的输出是这样的:
Some statements 1
Some statements 2
未应用时是这样的:
a()
Some statements 1
a()
Some statements 2
我不喜欢的是我必须使用硬盘驱动器来加载编译的功能。可以在不将其写入临时模块temp.py
并从中导入的情况下完成吗?
第二个问题是关于将装饰器放在上面f
:@replace
。当我这样做时,使用这个装饰器inspect.getsourcelines
返回文本。我可以从的文本中f
手动删除。f
但这将非常危险,因为可能应用了多个装饰器。所以我求助于老式的装饰语法f = remove_1(f)
,它完成了这项工作。但是,是否可以允许正常的装饰技术@replace
?