在Python中的函数内动态更改函数

时间:2014-06-12 17:27:38

标签: python string exec function

尝试在Python中基于从字符串中提取函数来进行一些动态函数更改:

目标是能够在运行时和基于用户输入从字符串解释的新函数替换函数。

我一直在尝试使用exec函数作为将文本解释为函数的一种方式,但在关于更新其他函数中的函数时它似乎不起作用。

到目前为止我所拥有的是

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

这很好,但是 -

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

失败,可以在函数中使用吗?

1 个答案:

答案 0 :(得分:1)

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 2,其中使用exec时禁用正常的本地名称空间优化。在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())

但是像所有全局变量一样,应该避免这种副作用。