関数テキストをバイトコードにコンパイルして実行する前に、前処理を試みることにしました。これは単にトレーニング用です。それが使用されるのに満足のいく解決策になる状況を私はほとんど想像しません。この方法で解決したい問題が1つありましたが、最終的にはより良い方法が見つかりました。したがって、これはトレーニングと新しいことを学ぶためだけのものであり、実際の使用法ではありません。
コンパイル前にかなり変更したいソースコードを持つ関数があると仮定します。
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
か?
2番目の質問は、デコレータを上に配置することについてですf
:@replace
。これを行うと、このデコレータでテキストをinspect.getsourcelines
返します。のテキストf
から手動で削除できます。f
ただし、複数のデコレータが適用されている可能性があるため、これは非常に危険です。そこで、私は古いスタイルの装飾構文に頼りましたf = remove_1(f)
。しかし、それでも、通常の装飾技術を使用することは可能@replace
ですか?