这是一个简单的代码,说明了问题的本质:
class test:
def __init__(self):
self.var = 0
def set(self, val):
self.var = val
print eval('map(lambda x: self.var*x, [1,2,3,4,5])')
f = test()
f.set(10)
它说
NameError: global name 'self' is not defined
我知道很多人不喜欢eval,但在我的情况下我必须使用它,因为它在程序执行期间从用户输入的字符串中执行数学公式。 任何建议都非常感谢!提前谢谢!
答案 0 :(得分:9)
尝试:
eval('map(lambda x, self=self: self.var*x, [1,2,3,4,5])')
奇数self=self
将从外部上下文创建self
的副本到内部上下文(lambda表达式的“主体”)。
答案 1 :(得分:7)
这是一个棘手的情况。首先,您可以使用以下方法:
class test:
def __init__(self):
self.var = 0
def set(self, val):
self.var = val
print eval('map(lambda x,self=self: self.var*x, [1,2,3,4,5])')
f = test()
f.set(10)
理由并不容易解释......但是试试吧。
写作时
lambda x: self.var * x
创建的是一个“闭包”,它将当前变量“self”捕获为lambda表达式中的非局部变量,因为self是当前环境中的局部变量。
当这个lambda由eval
构建时,但是self
中的局部变量eval
不可见,因此生成的lambda函数将引用全局在这种情况下不存在的变量self
。
答案 2 :(得分:7)
Eval()还支持分别设置全局和局部变量,因此您可以执行以下操作:
class test:
def __init__(self):
self.var = 0
def set(self, val):
self.var = val
print eval('map(lambda x: self.var*x, [1,2,3,4,5])', dict(globals().items() + [('self', self)]))
f = test()
f.set(10)
更新:以上示例现在维护以前的全局和局部变量。
答案 3 :(得分:2)
虽然我确定有一种方法可以在没有eval的情况下执行此操作,但您是否尝试过使用字符串格式化?
eval('map(lambda x: %s*x, [1,2,3,4,5])'%self.var)
答案 4 :(得分:0)
更通用的答案是将局部变量传递到eval环境
eval function支持另外两个参数,即全局和局部变量。因此,例如,您可以通过传递:
来解决问题而无需更改函数eval(map(lambda x: self.var*x + myvar, [1,2,3,4,5]), dict(self=self, myvar=123))