2010-08-30 73 views
22

我有一個包mypack,其中包含模塊mod_amod_b。我打算在包本身,mod_a自由地輸入:Python:包中的'Private'模塊

import mypack 
import mypack.mod_a 

不過,我想繼續mod_b獨家使用的mypack。這是因爲它僅僅是爲了組織後者的內部代碼而存在。

我的第一個問題是,在Python編程中有一個公認的做法是擁有這樣的「私有」模塊嗎?

如果是,我的第二個問題是,向客戶表達這種意向的最佳方式是什麼?我是否在名稱前加下劃線(即_mod_b)?或者宣佈一個子包private並將所有這些模塊放在那裏是一個好主意?

回答

13

我已經解決的解決方案是創建一個子包「私人」,並將所有模塊我想隱藏在那裏。通過這種方式,他們保持收起狀態,使mypack的模塊列表更清晰並且更易於解析。

對我而言,這看起來並不平庸。

+0

我將在近6年後發佈這篇文章,提供與您相同的問題和動機。私人子包方法仍然是你採取的方法還是你從那以後嘗試了其他方法? – 2016-06-29 21:59:10

+2

是的。我仍然在使用這種方法。還沒有找到更好的選擇。 – 2016-07-07 05:45:46

+3

感謝您的更新,並首先提出了這種方法。我在「private」子包名稱前添加一個'z_',以便它在IDE代碼完成下拉菜單中最後顯示。我在子包的'__init __。py'中使用相對導入來僅公開「公共」函數。在PyCharm和Jupyter中,爲了保持內部模塊的名稱不超出下拉列表,每個模塊必須具有與模塊名稱相同的函數,並且必須將該函數導入到__init __。py中。你可能已經知道所有這些,但如果不是這樣的話。如果你想讓我擴大爲答案,請讓我知道。 – 2016-07-07 15:16:39

2

Python並不嚴格知道或支持「私有」或「受保護的」方法或類。有一個約定,前綴爲單個下劃線的方法不是官方API的一部分,但我不會在類或文件上執行此操作 - 這很醜陋。

如果有人真的需要繼承或訪問mod_b,爲什麼要阻止他/她這樣做?您始終可以在文檔中提供首選API,並在模塊中記錄您不應直接訪問它並使用mypack替代。

+3

我可以像'mod_a'一樣訪問'mod_b'。但是,假設有20個模塊類似於'mod_b'。因此,當客戶端在編輯器中輸入'mypack.'時,智能感知將列出全部25個私有模塊和公共模塊。這會讓我的代碼更難以探索。這就是我想「隱藏」那些不適合客戶端的模塊的原因。至於文件,人們通常更喜歡探索閱讀文件。 – 2010-08-31 17:22:57

+0

正如Matt Joiner所說,不要將'mod_b'導入你的'__init __。py'。我建議你也查看'__all__'特殊變量。如果這些工作都沒有完成,問題出在Intellisense上。 – ssokolow 2010-09-04 21:33:30

+3

ssokolow,請參閱Matt的回答下的第三條評論。即使在'mypack/__ init __。py'中未導入mod_b',在客戶端代碼中輸入'import mypack.mod_b'仍然可以成功。這是因爲Python不需要將嵌入式模塊導入頂級導入模塊(例如'mypack.mod_b')以進行工作。 – 2010-09-05 06:24:29

6

雖然沒有明確的私人關鍵字,但是有一個約定會將私有函數以單個下劃線開始,但雙引號下劃線會使其它約束不能從模塊外輕鬆調用該函數。請參閱從PEP 8

- _single_leading_underscore: weak "internal use" indicator. E.g. "from M 
    import *" does not import objects whose name starts with an underscore. 

- single_trailing_underscore_: used by convention to avoid conflicts with 
    Python keyword, e.g. 

    Tkinter.Toplevel(master, class_='ClassName') 

- __double_leading_underscore: when naming a class attribute, invokes name 
    mangling (inside class FooBar, __boo becomes _FooBar__boo; see below). 

- __double_leading_and_trailing_underscore__: "magic" objects or 
    attributes that live in user-controlled namespaces. E.g. __init__, 
    __import__ or __file__. Never invent such names; only use them 
    as documented. 

以下要使整個模塊私有的,不包括它__init__.py文件。

+4

Aterrel,你的意思是「不包含在'__init __。py'」中?是否不要在'__init __。py'中放置語句'import mod_b'?如果是這樣,那仍然不能解決我的問題。客戶端仍然可以像公共模塊一樣導入'mod_b':import mypack.mod_b'。或者你的意思是別的嗎? – 2010-08-31 16:44:09

+1

因此,它不會嚴格執行該模塊是私人的,就像單個下劃線很弱。但是如果沒有明確地導入它,它就不會顯示出來,這仍然非常私密。我想你可以用兩個主要的下劃線來命名文件,但我從來沒有玩過這個。 – aterrel 2010-09-01 03:17:36

+1

感謝您的答覆。我正在解決的解決方案是在'mypack'下創建一個'private'子包,並將所有模塊都放在'隱藏'中。這有助於我更輕鬆地探索代碼(例如通過智能感知),將所有未被充分利用的絨毛都去掉。 – 2010-09-02 06:20:11

21

我用一個下劃線前綴私有模塊將意圖傳達給用戶。在你的情況下,這將是mypack._mod_b

這與PEP8的建議相同(但不完全類似),當它被Python模塊包裝時,用帶有下劃線的名稱命名C擴展模塊;即_socketsocket