2011-05-23 178 views
4

問題:有沒有辦法讓在python中使用字符串做一個函數對象從字符串創建函數對象


信息:我正在研究一個項目,我將數據存儲在sqlite3服務器後端。沒有什麼可以爲此瘋狂的。 DAL類通常是通過代碼生成完成的,因爲代碼非常單調。但是這給了我一個想法。在python中找不到屬性時,如果你定義了函數「getattr」,它會在出錯之前調用它。所以我通過解析器和邏輯樹來設計它,我可以動態生成我第一次調用時需要的代碼,然後將函數對象保存爲本地attrib。例如:

DAL.getAll() 

#getAll() not found, call __getattr__ 

DAL.__getattr__(self,attrib)#in this case attrib = getAll 

##parser logic magic takes place here and i end up with a string for a new function 

##convert string to function 

DAL.getAll = newFunc 

return newFunc 

我已經試過編譯功能,但高管,和eval是遠不能令人滿意的是能夠完成這種壯舉的條款。我需要一些能夠實現多行功能的東西。除此之外,還有另外一種方法可以做到這一點,不需要將其寫入磁盤?我再次嘗試動態創建函數對象

P.S .:是的,我知道這有可怕的安全和穩定性問題。是的,我知道這是一個非常無效的方式。我關心的?沒有。這是一個概念證明。 「python可以這樣做嗎?它可以動態創建一個函數對象」是我想知道的,而不是一些優越的選擇。 (儘管在回答手頭問題後可以隨時處理優秀的替代方案)

+0

「exec和eval在能夠完成這種功能方面遠遠不能令人滿意」?什麼? 'exec'完全可以。你有什麼**具體**錯誤或問題? – 2011-05-23 13:47:01

+1

嘗試從exec中返回一些東西。 – Narcolapser 2011-05-23 13:50:29

+0

'exec'只是運行東西,他們在罐子上做他們所說的。 'a = eval(「123」)'將綁定123到'a'。你得到表達的價值。 – Skurmedel 2011-05-23 13:53:18

回答

16

下使您在字符串中的字典d定義符號:

d = {} 
exec "def f(x): return x" in d 

現在d [「F」]是一個函數對象。如果你想在你的字符串代碼使用變量從你的程序,你可以通過d發送此:

d = {'a':7} 
exec "def f(x): return x + a" in d 

現在d [「F」]是動態綁定到d ['一個函數對象「]。當你改變d ['a']時,你改變了'f'的輸出。

+2

正如S.Lott所說的,如果你只是在沒有「in」的情況下運行exec,你將會在你當前的命名空間中得到一個新的函數。 exec「def f(x):return x」會給你一個新的函數對象f,準備在你的代碼中使用。 – Gurgeh 2011-05-23 14:42:45

+0

這就是我一直在尋找的。我想我缺少的是我沒有想到把'def'放到我的執行聲明中。但這正是我想要的。謝謝。 – Narcolapser 2011-05-23 21:13:01

+1

即使在「從數學導入*」之後,如果用sin(x)替換x,這也不起作用。似乎只適用於簡單的數學運算,如x + 1.0。 – Taozi 2015-08-01 02:54:58

0

如果它僅僅是概念上的證明,那麼eval和exec都很好,你也可以用pickle strings,yaml strings和任何東西來做到這一點否則你決定寫一個構造函數。

+1

嘗試從exec中返回一些內容。 – Narcolapser 2011-05-23 13:52:04

+0

這是要走的路。使用現有的解析器來解析您的字符串,然後讓它填充函數對象中的變量。如果它是一個完整的函數,那麼你將不得不得到一個更強大的解析器。 – wheaties 2011-05-23 14:51:01

+0

賓果,像PIL的'tostring'和'fromstring'方法一樣喜歡yamls對象的創作,這看起來很有趣。 – 2011-05-23 15:58:08

0

難道你不能這樣做嗎?

>>> def func_builder(name): 
... def f(): 
... # multiline code here, using name, and using the logic you have 
... return name 
... return f 
... 
>>> func_builder("ciao")() 
'ciao' 

基本上,組裝一個真正的函數,而不是組裝一個字符串,然後試圖編譯成一個函數。