2010-03-06 59 views
10

我剛剛讀過一篇文章,該文章將我介紹給一個新概念:到目前爲止,我確信python軟件包(即具有__init__.py文件的目錄)的行爲與java軟件包的行爲完全相同,即 - 小小的名稱空間安排代碼(減去java的「包」範圍)。 但是,根據這個鏈接: A Short Digression Into Multi-File Modules,如果我把我在同一個「包」中的所有文件:Python包(多文件模塊)的行爲與一個大模塊完全相同嗎?

文件的整個集合呈現給其他的Python代碼作爲一個單獨的模塊 - 好像所有的函數和類是在一個單一的.py

所以現在我認爲我對python「包」的完整理解是錯誤的。而且 - 它完全不是一個軟件包,而是作者提到的「多文件模塊」。

因此,根據我的理解,無論我將我的funcs和classes劃分爲多少個文件,從包的外部看起來好像我從包中的所有文件中取出所有代碼,它在一個與包相同的大文件中,即作爲一個模塊。

例如,如果我有以下文件結構:

/base 
    /animals 
     /__init__.py 
     /dog.py 

和dog.py:

def bark(): 
    print "woof" 

它應該是完全一樣的有:

/base 
    /animals.py 

和animals.py:

在第一種情況下

from base import animals 
animals.bark() 

當然收益率的這種:

因此,這未來一段代碼應在這兩種情況下運行良好

Traceback (most recent call last): 
    File "<console>", line 1, in <module> 
AttributeError: 'module' object has no attribute 'bark' 

缺少什麼我在這裏?我發現,「動物」確實被視爲一個模塊,但看起來我仍然必須明確指出animals.dog.bark,即包的內部文件結構不是從外部抽象出來的。

我是否遺漏了作者的觀點,或者只是沒有正確實施?

===編輯===

只是爲了確保沒有人錯過該線路報價:

好像所有的功能是在一個單身。PY

不管如何實際訪問此funcs中和類,以上報價明確規定,如果你在文件中的一個FUNC1和FUNC2文件B中,無論哪條路徑將它們從接近,如果我們將此路徑表示爲X,則根據上述報價,X.func1X.func2都應該起作用。

+0

我無法在鏈接頁面上找到該報價。小心再試一次? – 2010-03-06 14:28:00

+0

@Ignacio:http://diveintopython3.org/case-study-porting-chardet-to-python-3.html#multifile-modules – unutbu 2010-03-06 14:48:35

+0

@ignacio - 抱歉,更正鏈接 – olamundo 2010-03-06 14:51:51

回答

4

作者已經過分簡化了一些東西。他說,在animal下的所有內容都可以看作是在同一個模塊中,儘管事實上animal.dog中的名稱將存在於它們自己的命名空間中。

+0

好,很好。我以爲我錯過了一些東西:) – olamundo 2010-03-06 16:10:26

4

也許重要的是,一個包只是一個特定類型的模塊。

/base 
    /animals 
     /__init__.py 
     /dog.py 

這只是意味着什麼,你在或導入到定義將__init__.pyanimals模塊內部可見。

所以animals是一個模塊(這是一個包),而animals.dog是一個模塊,它是animals的子模塊,但不是包。

這也意味着,如果你有一個簡單的模塊animals,你可以在下一個版本中用一個同名的軟件包取代它,並且安排好讓你的用戶不會注意到它們的區別。

如果你想從封裝的子模塊的所有類組成一個單一的用戶可見的模塊(命名空間),你必須定義如下一行每個子模塊,在__init__.py

from animals.dog import * 
+0

請參閱我添加到我的問題中的修改 - 我認爲這清楚地表明這個答案沒有提及作者的觀點(除非我在你的答案中也缺少一些東西:)) – olamundo 2010-03-06 15:07:28

+0

你鏈接的文本肯定是錯誤的,容易被誤解。但我的答案只是我認爲對於一個密切相關的問題的明智答案,並且還顯示瞭如何使它成爲現實 - 如何讓它看起來像所有函數和類都在同一個.py文件中定義。鏈接文本暗示這是自動的,但不是,它只是一種可能性。 – u0b34a0f6ae 2010-03-06 16:11:34

+0

但是,在更高層次上,寫入*是真實的,因爲程序包會收集儘可能多的.py文件的內容,只需要在單個頂級模塊名稱後面添加。但是,它不會立即在模塊名稱空間中收集所有屬性。 – u0b34a0f6ae 2010-03-06 16:12:58

0

我可以沒有真正解釋它,但也許下面的代碼將有所幫助。如果我離開你的第一個文件結構,因爲它是,而是修改第二要有在animals.py文件中的以下內容:

class Dog: 
    def bark(self): pass 
dog=Dog() 

然後在這兩種情況下,

from base import animals 
animals.dog.bark() 

會工作。

+0

好吧,是的,在這種情況下,兩者都可以工作。但作者的說法比這更強大 - 模塊表現爲一個大模塊。 你已經證明了,一個包中的模塊表現得像一個具有屬性的大模塊,我相信大多數人都知道的東西:) 引用表單作者:「好像所有的*函數*和*類*是在一個單一的.py「 - 這明確意味着animals.bark應該足夠。 – olamundo 2010-03-06 14:57:07

1

不是一個真正的答案,但我還沒有允許評論(嘆息!):

由於diveintopython的是大量使用/引用/引用的Python程序員資源(當他們開始有至少)你應該真的聯繫作者關於這個缺陷,因爲它也會誤導別人。 diveintopython3的主頁上有一些聯繫信息,您也可以將它作爲github上的問題提交。

相關問題