2014-12-06 26 views
3

如果我EVAL的东西在Python:是否有可能从上层栈帧获取locals()和globals()?

eval("a + b") 

这将使用当前的范围(当地人和全局)计算表达式。

我正在开发的内容要求对表达式进行“稍后”评估。这个词意味着我想保留当前范围(即locals()globals())。但是我希望透明地传递这些值,或者从上层堆栈帧中获取它们。考虑此实现(实际上,这其中存在):

def __eval(self, expr): 
    if isinstance(expr, (list, tuple, set, frozenset, dict, Expression)): 
     return Expression.eval(expr, self) 
    elif callable(expr): 
     try: 
      return expr(self) 
     except (AttributeError, IndexError, KeyError, TypeError): 
      return UNDEFINED 
    else: 
     try: 
      return eval(expr, {}, {'self': self}) 
     except (AttributeError, IndexError, KeyError, TypeError): 
      return UNDEFINED 

这种实现方式如下:

  • 如果我使用一个表达式对象(其实我开发了这样的对象),那么我评价这种表达使用当前对象(毕竟这个函数是一个方法)。这部分不需要帮助,它得到了充分的发展。
  • 如果我使用可调用对象,则执行可调用对象(例如lambda表达式)。
  • 如果我使用一个字符串,那将是一个python表达式,我希望使用调用时间locals()globals()执行此类评估。

我知道我可以明确地呼吁:

o._O__eval("self.a + self.b", globals(), locals()) 
#THIS WOULD REQUIRE to alter the method to allow two additional dict parameters 
#NO, I will not call this function directly, but lets follow the example 

但我想获得这样的globals()locals没有传递给它明确的用户,并利用这些值在eval

问题:是否有可能从上层堆栈帧获取locals()globals()

+2

在这个设计中,请考虑“如果每个人都想做同样的事情你会怎样是?”问题。也就是说,假设你得到你想要的,然后我想编写另一个调用你的'__eval'的便利函数。我该如何告诉它,“不,不是,这个堆栈框架继续上升到另一个层次”? – 2014-12-06 16:30:46

+0

如果您敢于调用'scope ['$ eval'](“a + b”)'这是我在这里不会解释的原因 - 调用__eval的实际方法(是的,它是一种AngularJS端口, Python,但部分),那么你会使用调用时间的词法范围(这样的词法范围有一个额外的处理,让'self'指向当前的$ scope对象)。它现在工作:)。 – 2014-12-08 13:49:12

+0

但是,尽管我问了这个奇怪的用例,但它不是最常用的用例。 $ eval将总是在$ watch调用中调用(毕竟,它是 - 部分是AngularJS $ rootScope端口)。 – 2014-12-08 13:51:29

回答

3

你真的应该考虑只传递globals()locals()

def __eval(self, expr, eval_globals=None, eval_locals=None): 
    if eval_globals is None: 
     eval_globals = globals() 
    if eval_locals is None: 
     eval_locals = eval_globals() 

如果这不是一个选择,你可以访问与sys._getframe() function父框架,和当地人和全局属于该框架:

def __eval(self, expr, eval_globals=None, eval_locals=None): 
    call_frame = sys._getframe(1) 
    eval_globals, eval_locals = call_frame.f_globals, call_frame.f_locals 
+0

现在测试:) ... – 2014-12-06 16:32:03

相关问题