我決定嘗試在函數文本被編譯爲字節碼並執行後對其進行預處理。這僅僅是爲了訓練。我幾乎不能想象它會是一個令人滿意的解決方案。我遇到了一個我想用這種方式解決的問題,但最終找到了一個更好的方法。所以這只是爲了訓練和學習新東西,而不是真正的用法。在運行時bofore編譯中預處理函數文本
假設我們有一個功能,這是我們希望的源代碼在編譯之前相當多的修改:
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
?
你應該修改AST,而不是源。 –