2014-01-14 45 views
0

课间我做的代码生成和我结束了与源的字符串,看起来像这样的时候:的Python的exec()调用的拉姆达

来源

import sys 
import operator 

def add(a,b): 
    return operator.add(a,b) 

def mul(a,b): 
    return operator.mul(a,b) 

def saveDiv(a,b): 
    if b==0: 
     return 0 
    else: 
     return a/b 

def subtract(a,b): 
    return operator.sub(a,b) 

def main(y,x,z): 
    y = int(y) 
    print y 
    x = int(x) 
    print x 
    z = int(z) 
    print z 
    ind = lambda y,x,z: mul(saveDiv(x, add(z, z)), 1) 
    return ind(y,x,z) 

print main(**sys.argv)"" 

执行

当我执行使用exec()代码,然后通过stdoutIO()

01管道它

工作

args={'x':"1",'y':"1",'z':"1"} 
source = getSource() 
sys.argv = args 
with stdoutIO() as s: 
    exec source 
s.getvalue 

不工作

class Coder(): 

    def start(self): 

     args={'x':"1",'y':"1",'z':"1"} 

     source = getSource() 
     sys.argv = args 

     with stdoutIO() as s: 
      exec source 

     return s.getvalue 

print "out:", Coder().start() 

而且stdoutIO()是这样实现的:

class Proxy(object): 

    def __init__(self,stdout,stringio): 
     self._stdout = stdout 
     self._stringio = stringio 

    def __getattr__(self,name): 
     if name in ('_stdout','_stringio','write'): 
      object.__getattribute__(self,name) 
     else: 
      return getattr(self._stringio,name) 

    def write(self,data): 
     self._stdout.write(data) 
     self._stringio.write(data) 

    @contextlib.contextmanager 
    def stdoutIO(stdout=None): 
     old = sys.stdout 
     if stdout is None: 
      stdout = StringIO.StringIO() 
     sys.stdout = Proxy(sys.stdout,stdout) 
     yield sys.stdout 
     sys.stdout = old 

问题

如果我在类之外执行代码,但是当我在类中运行它时,会发生这个错误。我该如何解决或避免这个问题?

File "<string>", line 29, in <module> 
    File "<string>", line 27, in main 
    File "<string>", line 26, in <lambda> 
    NameError: global name 'add' is not defined 

感谢

+0

你是怎么在课外执行的? – aIKid

+0

如果我在任何一个类中运行exec(源代码),它会中断。但是,如果我在外面运行它(不知道如何调用环境),因为它在我的示例中显示,它工作正常。 –

+0

你能发布一个(非)工作示例,以便我们可以重现您的失败吗? –

回答

2

当你运行exec expression,它执行在当前范围包含在expression代码(见here)。显然在一个类中,表达式中的函数在运行main之前已经超出了范围。我真的不知道为什么(在我看来,它应该工作),但也许有人可以在评论中添加完整的解释。

无论如何,如果你特别提供了一个用于评估表达式的范围(无论如何,这是一个很好的练习,这样你就不会污染你的名字空间),它在课堂上工作得很好。与

exec source in {} 

exec source 

,你应该是正确的:

所以,更换就行了!

这里我们在评估表达式时提供一个空字典作为globals()和locals()dctionaries。如果你愿意的话,你可以保留这本字典,或者像我在我的代码中演示的那样立即收集它。这一切都在上面链接的exec文档中进行了解释。

+0

谢谢!它非常完美! –

+1

@GeorgeKouzmov不客气。我应该补充一点,如果你保留字典,你将可以访问表达式中定义的函数。例如,你可以在'mydict'的exec源文件后面调用'print mydict ['add'](1,2)''。不知道这对你有什么用处,但我想我会提及它! –