9

Ruby使用require,Python使用import。他們是完全不同的模型,雖然我更習慣require模型,但我可以看到一些地方,我認爲我更喜歡import。我很好奇人們發現哪些東西特別容易 - 或者更有趣,比他們應該更難 - 與這些模型中的每一個。加載代碼的require和import方法有哪些優缺點?

特別是,如果您正在編寫新的編程語言,您將如何設計代碼加載機制?哪些「優點」和「缺點」會對您的設計選擇造成重大影響?

+2

爲什麼這應該是一個社區wiki?這是一個明確的,可回答的問題! – Dario 2009-12-04 20:34:20

+0

因爲我在問一個問題,答案可能是主觀的。人們肯定有一種個人偏好的方式。我對主觀偏好感興趣,如果他們背後有一個合理的理由,超越「我更喜歡這個」。 – 2009-12-04 20:42:43

+0

我很想知道問題的背景,你會根據導入還是要求選擇另一種語言? – 2009-12-08 19:58:03

回答

14

Python的import有一大特點,它捆綁了兩兩件事一起 - 如何找到進口什麼命名空間包含它

這將創建非常明確的代碼:

import xml.sax

這指定在哪裏找到我們想要由Python搜索路徑的規則來使用,代碼。

與此同時,我們要訪問的所有對象都位於此確切名稱空間下,例如xml.sax.ContentHandler

我認爲這是Ruby需求的一個優勢。 require 'xml'實際上可能會使命名空間XML或模塊中可用的任何其他命名空間內的對象,而不需要直接從require行顯示。

如果xml.sax.ContentHandler太長,你可能會在導入時指定一個不同的名稱:

import xml.sax as X 

而且現在X.ContentHandler下是avalable。

這樣Python需要你明確地構建每個模塊的命名空間。 Python的命名空間是因此非常「物理」,我會解釋我的意思:

  • 默認情況下,只有在模塊中直接定義的名稱在其命名空間中可用:函數,類等等。
  • 要添加到模塊的名稱空間,您明確地導入了您希望添加的名稱,將它們(通過引用)「物理地」放置在當前模塊中。

例如,如果我們有小Python包「過程」與內部子模塊machineinterface,我們希望市直包名,代表這個作爲一個方便的命名空間,這是和例子我們所能在「包定義」文件process/__init__.py寫:

from process.interface import * 
from process.machine import Machine, HelperMachine 

因此我們舉起一個通常來說是可訪問的process.machine.Machine高達process.Machine。我們以非常明確的方式將所有名稱從process.interface添加到process名稱空間。

Python的進口,我寫的好處是簡單地二:

  • 清除你有什麼用import
  • 明確時,你如何修改自己的模塊的命名空間(程序或爲其他人導入)
+0

我同意這是一個很好用的功能,但是我發現有一些像'__init __。py'這樣的學習曲線更加陡峭,如果由於某種原因你沒有靈活的目錄結構,這會使命名空間完全相同你想要的方式有點困難。 – 2009-12-04 20:39:43

+0

我想知道爲什麼你沒有「靈活的目錄結構」? – 2009-12-09 01:45:12

+0

@Bob:當然,這是缺點。我看到它的方式,您提到的優勢@ kaizer.se的交易學習曲線更陡。如果你問我,這是值得的。 – 2009-12-09 01:57:14

1

免責聲明,我絕不是Python專家。

我看到require超過import的最大優點就是您不必擔心理解名稱空間和文件路徑之間的映射。很明顯:這只是一個標準的文件路徑。

我真的很喜歡import所具有的命名空間的重點,但不禁要問,這種特殊的方法是不是太不靈活。據我所知,在Python中控制模塊命名的唯一方法是更改​​正在導入的模塊的文件名或使用重命名。此外,使用明確的命名空間,您可以通過其完全限定的標識符來引用某些東西,但是使用隱式命名空間,您無法在模塊本身內部執行此操作,並且這可能會導致潛在的歧義沒有重命名很難解決。

foo.py

class Bar: 
    def myself(self): 
    return foo.Bar 

這種失敗:

 
Traceback (most recent call last): 
    File "", line 1, in ? 
    File "foo.py", line 3, in myself 
    return foo.Bar 
NameError: global name 'foo' is not defined 

兩種實現使用的位置列表,從搜索,這在我看來是一個極爲重要的組成部分,無論你選擇的模型。

如果使用像require這樣的代碼加載機制,但該語言根本沒有全局名稱空間會怎麼樣?即任何地方都必須有名稱空間,但開發人員完全可以控制定義類的哪個名稱空間,並且該名稱空間聲明在代碼中顯式地發生,而不是通過文件名。或者,在全局名稱空間中定義一些內容會生成警告。這是一種兩全其美的方法,還是我缺少一個明顯的缺點?

+0

其實你可以返回'foo.Bar',如果你在'我自己'的方法中'import foo'就在它的上面。但是,當你可以返回'Bar'時,你爲什麼要這麼做? – 2009-12-09 00:36:42

+1

在這個例子中,顯然,是的,返回Bar正是你想要做的。但是,我正在編寫一些代碼,其中有些代碼是由其他作者編寫的插件。我需要特別小心不明確的命名空間。幸運的是,我剛剛從__future__ import absolute_import中發現了'',這幾乎完全緩解了這個問題。 – 2009-12-09 01:47:33

+1

爲什麼不把你的插件放在你的應用程序的目錄中,比如'插件',每個插件都有自己的子目錄?這樣,插件之間就不會有衝突,你可以__import__而不用做黑魔法,並用__subclasses__找到實現。如果插件作者像'導入字符串'那樣執行衝突導入,那不是你的問題,或者如果是的話,他們不再是真正的插件;) – 2009-12-09 02:20:36

3

require的一個不錯的屬性是它實際上是一個在Kernel中定義的方法。因此,您可以覆蓋它並實現您自己的Ruby包裝系統,這是例如Rubygems呢!

PS:我不是在這裏賣猴子補丁,而是Ruby的包系統可以被用戶重寫(甚至像python系統一樣工作)。當你編寫一門新的編程語言時,你不能把所有的東西都弄對。因此,如果您的導入機制可以從語言內部完全擴展(完全指向所有方向),那麼您將爲未來的用戶提供最好的服務。從自身內部不完全擴展的語言是進化的死衚衕。我會說這是Matz與Ruby合作的原因之一。

+0

我不會-1這個,但在Ruby中存在的猴子修補是有問題的,而不是我想鼓勵的東西。一個好的包裝系統可以簡單地修改搜索路徑並保留單獨的代碼加載。 – 2009-12-09 00:24:14

+0

嗯...我相當確定你不能在Ruby中模擬Python的導入系統。你可能會得到一些與之相似的東西,但這可能是一種徹頭徹尾的破解,它可能破壞各種代碼,如果你在生產環境中使用它,你會讓很多人失望。 – 2009-12-09 06:11:15

+0

-1因爲聲稱不賣猴子補丁而賣猴子補丁。同時也是對Python的導入機制一無所知(無論如何也願意苛刻)。我見過的第一個答案是,如果可以的話,我會不止一次地倒退。 – 2009-12-13 07:30:16

1

Python的導入提供了一種非常明確的命名空間:命名空間是路徑,您不必查看文件就可以知道它們在哪些命名空間中進行定義,並且文件不會與命名空間定義混雜在一起。這使得應用程序的命名空間方案簡單且快速理解(僅查看源代碼樹),並避免了像名稱空間聲明一樣的簡單錯誤。

一個不錯的副作用是每個文件都有它自己的私有名稱空間,所以在命名事物時不必擔心衝突。

有時命名空間也會變得煩人,像some.module.far.far.away.TheClass()這樣的東西在任何地方都可能很快讓你的代碼變得非常長而且無聊。在這些情況下,您可以使用import ... from ...並在當前一個注入另一個名稱空間的位。如果注入導致與要導入的模塊衝突,則可以簡單地重命名您導入的內容:from some.other.module import Bar as BarFromOtherModule

Python仍然很容易出現像循環導入這樣的問題,但它的應用程序設計不僅僅是在這些情況下必須指責的語言。

因此,python採取了C++ namespace#include並在很大程度上延伸它。另一方面,我沒有看到ruby的modulerequire以何種方式爲這些添加了新的東西,並且您有像全局命名空間混亂一樣的可怕問題。

+0

Ruby的要求在語言中是完全可擴展的。如果你不喜歡它的導入語義,你可以去改變它們!這不能用C++或python來完成,所以至少在這方面,Ruby會爲導入作品的方式增加一些重大新聞。 – akuhn 2009-12-09 02:03:16

+4

您可以像在Ruby中一樣自定義python導入機制。但在這兩種情況下,這聽起來像一個非常糟糕的主意。當兩個第三方模塊定製導入機制時會發生什麼?這種事情必須是標準的,而對於我來說,紅寶石的標準機制是不夠的。 – 2009-12-09 02:25:36

相關問題