如何使用Python从字符串定义一个函数

12

这是我的代码:

a = \
'''def fun():\n
    print 'bbb'
'''
eval(a)

fun()

但它显示错误:

Traceback (most recent call last):
  File "c.py", line 8, in <module>
    eval(a)
  File "<string>", line 1
    def fun():
      ^
SyntaxError: invalid syntax

那么我该做什么呢,

谢谢


你为什么需要使用eval()函数? - user2665694
4个回答

17

eval() 函数只能用于表达式。如果要执行语句,请使用 exec 函数:

exec """def fun():
  print 'bbb'
"""

但在这之前,请考虑您是否真的需要动态代码。大多数情况下,没有必要使用动态代码。


1
在Python3中,这现在是一个函数。您可能需要传递一个虚假的locals/globals字典,将赋值操作执行到已知的魔术值,并执行fun = myFakeLocals['magic_value'] - ninjagecko
1
@ninjagecko:他的代码使用的是Python 2语法,所以我认为他希望得到相同方言的回应。不过将其转换为Python 3也很简单,只需添加括号即可。也不需要传递locals/globals。 - Matti Virkkunen
哦,确实你是对的;我把它和另一种使用locals()[functionName]的方法混淆了,如果你事先不知道名称为fun - ninjagecko
eval 不仅仅适用于表达式; 只是 str 参数必须为表达式,但它也可以接受任意复杂度的代码对象。如果将其与 compile 混合使用,您可以评估任意代码,例如 eval(compile(mystr,'<string>', 'exec')) 运行良好(并且在 Python 2 和 Python 3 上的运行方式相同,不像 exec)。 - ShadowRanger
但在此之前,请考虑一下您是否真的需要动态代码。绝大多数事情都可以不用它来完成。否则我就得写VBScript了。绝大多数事情都可以不用它来完成,并且通过更好的并行化实现会更好(如果C语言内置函数到shellcode的预编译器,线程将更加实用,而无需使用更高级的语言或为每个线程过程创建全局函数以避免全局范围被一次性使用的东西所淹没)。 - Dmytro

3

Eval只计算表达式,而exec执行语句。

因此,您可以尝试像这样做:

a = \
'''def fun():\n
    print 'bbb'
'''
exec a

fun()

2

非表达式的 eval 参数必须首先进行 compile 编译;只有字符串被处理为表达式,因此完整语句和任意代码都需要使用 compile

如果与 compile 混合使用,则可以 eval 任意代码,例如:

eval(compile('''def fun():
    print('bbb')
''', '<string>', 'exec'))

以上代码可以正常工作并在Python 2和Python 3上表现一致,这与exec不同(它是Python 2中的关键字,在Python 3中是函数)。


1
在 Python 3.7 中执行此操作会返回 "None" 而不是函数对象。 - Jonno_FTW
@Jonno_FTW:它不应该返回它(def不是表达式,它不会产生任何可分配的东西),它只是将其添加到当前作用域(如果在函数内部,则为本地作用域,否则为全局作用域,并且您可以选择传递替代的全局或本地字典)。当与字符串或以“eval”模式编译时使用时,eval仅预计会产生有用的返回值;在“single”或“exec”模式下,它不会评估表达式。 - ShadowRanger

1
如果你的逻辑非常简单(即只有一行),你可以使用eval一个 lambda 表达式:
a = eval("lambda x: print('hello {0}'.format(x))")
a("world") # prints "hello world"

正如其他人提到的那样,如果可以的话,最好避免使用eval


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接