2009-11-27 64 views
3

假設你有一個Python包僞裝類

./a 
./a/__init__.py 
./a/_b.py 

以下佈局內__init__.py的真實模塊,您有

from _b import * 

和內部_b.py你有

class B(object): pass 

如果您從交互式提示輸入

>>> import a 
>>> a.B 
<class 'a._b.B'> 
>>> 

我怎樣才能完全隱藏_b的存在?

我想解決的問題如下:我想要一個導入「隱藏」模塊和類的外觀包。從門面可用的類(在我的案例a)保持穩定,並保證將來。然而,我希望自由地將課堂安置在「引擎蓋下」,因此隱藏了模塊。這很好,但是如果某些客戶端代碼使用外觀提供的對象,這個pickle數據將引用隱藏的模塊嵌套,而不是外觀嵌套。換句話說,如果我將B類重新定位到模塊_c.py中,客戶端代碼將無法取消激活,因爲醃漬類指的是已移動的a._b.B。如果他們提到a.B,我可以根據需要儘可能多地重新定位B類,而不會破壞醃製數據。

回答

5

嘗試:

B.__module__= 'a' 

順便說一句,你可能需要一個絕對的導入:

from a._b import * 

因爲沒有新的明確的點語法相對進口要離開(see PEP 328)。

ETA再評論:

我會明確地將模塊設置爲每類

是的,我不認爲有周圍的一種方式,但你至少可以自動執行它,在__init__末:

for value in globals().values(): 
    if inspect.isclass(value) and value.__module__.startswith('a.'): 
     value.__module__= 'a' 

(對於新式的類只有你可以逃脫isinstance(value, type)代替inspect。如果模塊沒有爲__main__運行,你可以使用__name__而不是硬編碼'a'。)

+0

這可能是一個很好的解決方案,我也沒多想,但我會明確地設置模塊,每類。有沒有「更好」的把戲? (我的意思是,這已經足夠好了,但只是爲了好奇) – 2009-11-27 12:59:50

+0

您可以在__init__中設置__module__屬性,也可以在 – miku 2009-11-27 13:05:36

+0

中設置好PEP。我每次都有遺忘的可能(我主要是爲了兼容性而使用python 2.4) – 2009-11-27 13:06:24

2

您可以設置__module__變量Class B

class B(object): pass 
B.__module__ = 'a' 

對於類,函數和方法,該屬性包含定義對象的模塊的名稱。

或者在你__init__.py一旦定義它:

from a._b import B # change this line, when required, e.g. from a._c import B 
B.__module__ = 'a'