2010-08-31 45 views
1

我有以下代碼:蟒蛇:與本地類名混淆

C1 = f() 
C2 = f() 

,它似乎很好地工作:C1是C2返回False

def f(): 
    class XYZ: 
     # ... 
    cls = type('XXX', (XYZ,), {}) 
    # ... 
    return cls 
我現在用的是如下

,有兩個類的類屬性之間沒有衝突,等等

問題1

這是爲什麼? C1和C2如何顯示爲類

<'__main__.XXX'> 

但還不是相同的類?

問題2

是有一些問題的事實,我有兩種不同類型的兩個相同的名字呢?

問題3

我希望能夠代替寫:

f('C1') 
f('C2') 

具有同樣的效果。可能嗎?

問題4

如果我想C1看起來像一個普通班,不主要 .XXX,是它確定地說:

C1.__name__ = '__main__.C1' 

回答

2

問題3

cls.__name__成爲你想要的任何東西(帶着對delnan的建議的點頭)

def f(clsname): 
    class XYZ: 
     # ... 
    XYZ.__name__ = XYZ 
    # ... 
    return XYZ 

問題1

之所以c1 is not c2是,它們是存儲在內存中的兩個不同位置的兩個不同的對象。

問題4

嘗試回答問題1,看看它是如何工作的,你

問題2

可以複雜的調試,他們的階級屬性__name__共用一個價值,這足夠糟糕,需要努力避免。 (見問題3)。儘管他們沒有相同的名字,但我會保留。一個名爲C1,另一個名爲C2(至少在您展示的範圍內)。如果你將它們傳遞給函數,則命名該範圍將是相同的,他們通過傳遞的參數名稱)

其實,我很肯定他們沒有同樣的名字試圖告訴我,否則可能會導致我把音樂變得更響,假裝我聽不到你。

迴應置評

這是可以做到,但它只是錯誤的。無論如何,我會說明,因爲它的照明:

def f(clsname): 
    class XYZ(object): 
     pass 
    XYZ.__name__ = clsname 
    globals()[clsname] = XYZ 

f('C1') 
f('C2') 

print C1 
print C2 

這只是工作通過堅持在全局類字典由clsname鍵。但是有什麼意義呢?你可以將它粘在全局字典的任何名稱中,因爲這只是另一項任務。你最好只從函數返回類,並讓調用者決定在自己的範圍內給予類的名稱。您仍將該類的__name__屬性設置爲傳遞給該函數以進行調試的字符串。

+0

您提出的代碼是什麼我原本。問題是,除非我說C1 = f('C1'),否則clsname在全球級別是未知的。我能否修正它,因此只需調用f('C1')就可以在全球範圍內引用C1類? 重新命名:我同意你的觀點;我只是指_ _ name _ _屬性是相同的。 – max 2010-08-31 19:44:37

+0

看來,根據delnan的回答「修復它」是一個壞主意。然後我想我會繼續使用C1 = f()方法,而不用擔心XXX裏面的內容是相同的。 – max 2010-08-31 19:52:22

+0

@ max。查看我的更新。您仍然可以控制分配給該類的'__name__'屬性以進行調試! – aaronasterling 2010-08-31 20:07:14

2

其實,你並不需要在cls = ...線都沒有。

>>> def f(): 
...  class C: 
...   pass 
...  return C 
... 
>>> f() is f() 
False 

原因:class(以及例如def)它遇到=每個函數被調用時,每次定義新的類。

至於cls.__name__,它真的沒有語義差別。這個名字對調試很有用(你不直接向用戶公開它,是嗎?)和反省,但它不應該是一個問題。但是,如果你絕對想擁有不同的名字,就可以返回前改變cls.__name__(也注意到C.__name__ = 'foo'C.__name__ == '__main__.foo'後!)。

問題3:有可能將它直接注入到全局命名空間中...... 不要這樣做。它沒有優勢,只有缺點:不明顯的副作用,不好的風格,它根本就是黑客,等等!

+0

明白了所以原來的代碼有沒有問題,只是有點調試/自省困難的 - 這不能沒有得到解決駭客或使用模式中的重複:C1 = f('C1')。是否正確? – max 2010-08-31 19:54:23