2010-04-07 30 views
2

我顯然在對Python範圍的理解很差的情況下工作。也許你可以幫忙。「庫」方法的範圍

背景:
我使用

if __name__ == "__main__" 

結構來我模塊(S)在執行 「自檢」。每次自測都會調用各種公共方法,並在開發模塊時打印結果以進行視覺檢查。

爲了保持 「普爾蒂」 和可管理的,我創建了一個小方法來簡化方法的調用測試:

def pprint_vars(var_in): 
    print("%s = '%s'" % (var_in, eval(var_in))) 

foo = "bar" 

與調用pprint_vars:

pprint_vars('foo') 

打印:

foo = 'bar' 

一切都很好。

問題陳述:
不開心,只是吻,我有腦小雨動我的方便,花花公子「pprint_vars」的方法到一個名爲「debug_tools.py」一個單獨的文件,只需輸入「debug_tools」每當我想訪問'pprint_vars'。

這裏是事情崩潰的地方。我希望

import debug_tools 

foo = bar 
debug_tools.pprint_vars('foo') 

繼續工作它的魔力和打印:

foo = 'bar' 

相反,它招呼我:

NameError: name 'some_var' is not defined 

非理性的信念:
我相信(顯然是錯誤的)該導入會將輸入方法(或多或少)與代碼「內聯」,因此變量範圍規則將保持類似於如果方法我們重新定義內聯。

請求幫助:
有人可以糾正我對誤區的理解嗎?

感謝, JS

+0

你確定你發佈了完全相同的代碼嗎?它不應該是'foo ='bar''嗎?我找不到錯誤信息中提到的'some_var'。 – 2010-04-07 23:39:14

+0

你是對的,菲利克斯。我很抱歉。我有(希望)糾正錯誤。 – 2010-04-07 23:49:06

+0

'__name__'成語通常寫成'if __name__' =='__main__「:',測試是否相等。它正好使用了__in__運算符,因爲它包含了測試,但有些意外。 – Todd 2010-04-08 02:30:01

回答

2

在Python中的每個文件是它自己的命名空間。一個函數被調用時,解析它的變量以下列順序:

  1. 局部變量(包括捕獲的變量或在封閉)
  2. (模塊)的全局變量
  3. 建宏

您可以使用(解釋器特定的)inspect模塊作爲框架列表導航調用堆棧。由於框架知道它的當地人,全局,建宏和父框架,你可以「看」的解釋,通過呼叫方這樣的眼(請僅用於調試):

import inspect 
def log_var(name): 
    f = inspect.currentframe().f_back 
    if name in f.f_locals: 
     print "local `%s` = %r" % (name, f.f_locals[name]) 
    elif name in f.f_globals: 
     print "global `%s` = %r" % (name, f.f_globals[name]) 
    elif name in f.f_builtins: 
     print "builtin `%s` = %r" % (name, f.f_builtins[name]) 
    else: 
     print "`%s` not found" % name 
2

「全球範圍」 實際上並不存在在Python。通常所說的「全球範圍」實際上是模塊範圍。也就是說,在模塊級別定義的名稱。將該功能放在另一個模塊中意味着其模塊範圍發生變化。

+0

作爲實現我的目標的首選方式,您會有什麼建議? – 2010-04-07 23:41:47

+0

使用各種'檢查。* frame *()'函數獲取調用者的框架,然後訪問框架的'f_locals'屬性以獲取本地:'inspect.getouterframes(inspect.currentframe())[1] [0] .f_locals [var_in] ' – 2010-04-07 23:52:59

0

EVAL接受兩個可選參數 - 全球當地 - 你可以指定爲背景來評價你的源:

print("%s = '%s'" % (var_in, eval(var_in, globals()))) 
+0

如果'var_in'應該位於完全不同的未知模塊中,這將無濟於事。 – 2010-04-07 23:57:48

1

我會推薦路過的當地人()的功能,像這樣......

def pprint_var(var_name, D): 
    print "%s = %r" % (var_name, D[var_name]) 

...

pprint_var(var_name, locals()) 

,如果你不希望出現這種情況,你可以使用檢查模塊或sys._getframe做同樣的事情,正如其他人所暗示的那樣d。

0

我遇到的基本問題是Python對於簡單對象沒有名稱的意義。對於方法,類等等,對於簡單的對象,沒有。

因此,在這種特徵變量的語言,我的「ppvar」功能會是這個樣子(僞代碼):

ppvar(var_name): 
    print("%s = '%s'", var_name, $var_name) 

我可以導入該文件包含的任何工程「ppvar」,並把它和它基本上會被「內聯」到我的代碼中。

唉這很可能是一個「函數式編程」的概念,不適合面向對象的方法。

所有語言都有優缺點。每種語言都有一些「簡單」的東西。能夠執行如下操作:

print("%s = '%s'" % (var.__name__, var) 

在Python中是(至今)不是可行的。好吧。