2014-06-12 23 views
1

試圖做一些動態的功能基於字符串的拉動作用在Python改變:動態變化的函數中的功能在Python

我們的目標是能夠與運行期間從一個字符串解釋的新功能替換功能,基於用戶輸入。

我一直在嘗試使用exec函數作爲解釋文本作爲函數的一種方式,但在關於更新其他函數中的函數時它似乎不工作。

我至今是

>>> exec("def test(x): print(x + 8)") 
>>> test(8) 
16 

這工作得很好,though-

>>> def newTest(newTestString): 
     initString = "def test(x): " 
     exec(initString + newTestString) 
>>> newTest("print(x + 20)") 
>>> test(10) 
18 

失敗,可以Exec同時功能中使用?

+0

這是Python 2還是3? –

回答

1

exec()可以在函數中使用,你只需要記住在新的對象已經創建的名稱空間。您需要從您的本地命名空間返回它:在Python 2,其中當使用exec當地正常的命名空間的優化被禁用

>>> def newTest(newTestString): 
...  initString = "def test(x): " 
...  exec(initString + newTestString) 
...  return test 
... 
>>> newTest("print x + 20") 
<function test at 0x10b06f848> 
>>> test = newTest("print x + 20") 
>>> test(10) 
30 

這隻作品。在Python 3,給exec()命名空間中來創建新的對象,然後檢索新的功能,並返回它:

>>> def newTest(newTestString): 
...  initString = "def test(x): " 
...  ns = {} 
...  exec(initString + newTestString, ns) 
...  return ns['test'] 
... 
>>> newTest("print(x + 20)") 
<function test at 0x110337b70> 
>>> test = newTest("print(x + 20)") 
>>> test(10) 
30 

此方法效果一樣好在Python 2,具有額外的優勢,當地命名空間優化也未被禁用。

原則上可以指示exec直接在您的全局命名空間的工作太多:

exec(initString + newTestString, globals()) 

但像所有全局這種副作用應該避免。

+0

你可以在全局變量中使用exec字符串嗎? (如果我正確地記得python2.x語法) - 我認爲在某個地方,'exec'開始接受與python3的exec函數兼容的元組... – mgilson

+0

@mgilson:你可以,但首選的方法是應該創建一個新的名稱空間。 –

+1

我認爲首選方法是根本不使用'exec' ;-) – mgilson