【问题标题】:Dynamically changing functions within functions in Python在 Python 中的函数内动态改变函数
【发布时间】:2014-06-12 17:27:38
【问题描述】:

尝试基于从字符串中提取函数在 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

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

【问题讨论】:

  • 这是 Python 2 还是 3?

标签: python string exec function


【解决方案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() 一个命名空间来创建新对象in,然后检索新函数并返回它:

>>> 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())

但与所有全局变量一样,应避免此类副作用。

【讨论】:

  • 你能exec string in globals()吗? (如果我没记错 python2.x 语法的话)——而且我认为在此过程中,exec 开始接受一个元组以与 python3 的 exec 函数兼容......
  • @mgilson:可以,但首选方法是创建一个新的命名空间。
  • 我认为最好的方法是根本不使用exec ... ;-)
  • @mgilson:我非常同意!我过去曾使用过exec,但是我需要生成一个函数对象,其签名与我包装的签名完全相同(因为内省将应用于它)。
  • @mgilson:使用exec 比使用compile 和函数类型构造函数更干净。
猜你喜欢
  • 1970-01-01
  • 2013-11-04
  • 2019-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多