2014-12-06 21 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

相關問題