2017-07-08 103 views
0

這個問題與其他人在這裏提出的問題類似,但在閱讀答案後,我並不理解它,並希望得到進一步的指導。Python中嵌套函數的作用域

在繪製新的代碼,我發現自己加入了很多語句,如:

print('var=') 
pprint(var) 

它變得乏味總是寫這一點,所以我想我可以使它成爲一個功能。因爲我想打印前行中的變量名,我想:

def dbp(var): 
    eval('print(\'{0}=\')'.format(var)) 
    eval('pprint({0})'.format(var)) 

所以後來我做不喜歡的東西:

foo = 'bar' 
dbp('foo') 

它打印

foo= 
'bar' 

這是所有很好,但是當我在功能中使用它時,事情會變得混亂。例如,做

def f(): 
    a = ['123'] 
    dbp('a') 
f() 

引發NameError(NameError:name'a'未定義)。

我的期望是dbp()可以讀取f()範圍內的任何內容,但顯然它沒有。有人能解釋爲什麼嗎?

此外,更好的方式打印一個變量的名稱,其後格式化的內容也值得讚賞。

+2

'foo'是本地模塊'DBP( )'在模塊範圍內,因此可以訪問模塊範圍。 'a'對'f()'是局部的''dbp()'不能訪問'f()的作用域。如果你在'f()'內部使用'def dbp()',那麼它就可以訪問f()的作用域。解決這個問題的辦法是通過'locals()',然後你可以使用locals()['a']',你不需要'eval()'語句。 – AChampion

+0

在這兩種情況下,您都會傳遞一個字符串,eval會嘗試打印該變量。如果該變量在eval的範圍內,則會打印該變量。否則,它不是。 –

+1

爲什麼你'eval()'第一個'print()'?不會'print('{0} ='。format(var))'做? – AChampion

回答

1

你真的應該看看其他的方式來這樣做。
logging模塊是一個非常好的習慣,您可以關閉並打開調試輸出。
的Python 3.6擁有f''字符串,這樣你將簡化這:

pprint(f'var=\n{var}`)` 

但是,這裏有一個例子(不推薦)使用locals()

In []: 
def dbp(var, l): 
    print('{}='.format(var)) 
    pprint(l[var]) 

def f(): 
    a = 1 
    dbp('a', locals()) 
f() 

Out[]: 
a= 
1 
+0

同意重新:伐木。我很久以前曾經使用它,並忘記了它。它總是感覺像小調試打印的矯枉過正,但小印刷似乎總是變成主要印刷......無論如何,我應該養成這種習慣。 – Andrew

-1

首先,id喜歡說eval對於任何將要運行該代碼的人來說都是高度安全風險。

但是,如果你絕對必須,你可以這樣做。

def dbp(var): 
    env = {'var': var} 

    # Adding global variables to the enviroment 
    env.update(globals()) 

    eval("print('{0}=')".format(var)) 
    eval('pprint(var)', env) 

def f(): 
    a = ['123'] 
    dbp('a') 

然後你可以做

>>> f() 
a= 
'a' 
+0

f()的作用域不在'globals()'中。 – AChampion

+0

看起來像無稽之談。不打印'['123']'。 –

+0

@AChampion你是對的,我忽略了這一點。你的答案是正確的。 –