Ответ 1
Try:
eval('map(lambda x, self=self: self.var*x, [1,2,3,4,5])')
Нечетный self=self
создаст копию self
из внешнего контекста во внутренний контекст ( "тело" лямбда-выражения).
Вот простой код, иллюстрирующий суть проблемы:
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, но в моем случае я должен использовать его, потому что он выполняет математическую формулу из строки, введенной пользователем во время выполнения программы. Любые предложения приветствуются! Спасибо заранее!
Try:
eval('map(lambda x, self=self: self.var*x, [1,2,3,4,5])')
Нечетный self=self
создаст копию self
из внешнего контекста во внутренний контекст ( "тело" лямбда-выражения).
Это сложная ситуация. Прежде всего в качестве обходного пути вы можете использовать:
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 является локальной переменной в текущей среде.
Когда эта лямбда построена с помощью eval
, однако эта локальная переменная self
не видна внутри eval
, и поэтому генерируемая лямбда-функция будет ссылаться на переменную global self
, которая не работает В этом случае не существует.
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)
Обновление: В приведенном выше примере теперь хранятся предыдущие глобальные и локальные переменные.
Хотя я уверен, что есть способ сделать это без eval, попробовали ли вы использовать форматирование строк?
eval('map(lambda x: %s*x, [1,2,3,4,5])'%self.var)
Более общий ответ: передать локальные переменные в среду eval
eval(map(lambda x: self.var*x + myvar, [1,2,3,4,5]), dict(self=self, myvar=123))