2014-01-20 293 views
1

我想了解python作用域規則。要做到這一點,我嘗試同一模塊訪問私人模塊變量從類

bar = "bar" 
_bar = "underscore" 
__bar = "double underscore" 

def foo(): 
    print bar 
    print _bar 
    print globals()["__bar"] 
    print __bar 

class Foo: 
    def __init__(self): 
     print bar 
     print _bar 
     print globals()["__bar"] 
     print __bar #NameError: global name '_Foo__bar' is not defined 

foo() 
Foo() 

它失敗NameError在訪問從類「非常私人」的變量。我無法在規範中找到任何有關這方面的信息。那麼,爲什麼它失敗了,這種行爲在哪裏描述?

+0

你可以發佈完整的輸出嗎?還是完整的異常消息? –

+0

是的,刪除是因爲 - 我驚訝地發現 - 即使使用獨立名稱__bar也會發生這種情況。您從文檔發佈的報價並沒有明確說明。 –

+0

@DanielRoseman:*當在類定義中文本出現的標識符*和*這種轉換獨立於使用標識符的語法上下文*這包括任何在類體中任何地方都是標識符的標識符,包括方法定義。無論它是屬性,全局還是本地都無所謂。 –

回答

3

在一個類定義中,所有名稱爲的起始都帶有雙下劃線;重寫爲包括類名作爲前綴。

這是一個功能,支持在類中標記名稱爲'private',並防止它被子類覆蓋。看到identifiers documentation

私人名稱重整:當該文本方式發生在類定義的標識符具有兩個開始或多個下劃線字符,並在兩個或多個下劃線並沒有結束,它被認爲是一個專用名稱那個班。在爲其生成代碼之前,專用名稱會轉換爲更長的形式。該轉換將在名稱前插入類名,並刪除前導下劃線和插入的單個下劃線。例如,名爲Ham的類中出現的標識符__spam將轉換爲_Ham__spam。這種轉換獨立於使用標識符的語法上下文。如果轉換的名稱非常長(超過255個字符),則可能會發生實現定義的截斷。如果類名只包含下劃線,則不進行轉換。

最好不要在模塊全局變量上使用雙下劃線前綴;沒有必要這樣做,單個下劃線就足以說明該值是模塊內部的。

如果您遇到這樣的值,請創建一個沒有損壞的別名,或使用globals()[name]

+0

那麼如何才能從課堂內部獲得雙重得分常數? 'globals()['__ bar']'看起來有點怪異。 –

+1

@PauloBu:或者使用'sys.modules [__ name __] .__ bar' ...最好不要使用雙下劃線名稱作爲全局變量,真的。 –

+0

是的,這是我的想法:) –