2009-11-09 77 views
19

在導入代碼的各種方式中,與其他方法相比,有哪些方法可以使用?這在短期 鏈接http://effbot.org/zone/import-confusion.htm指出Python(和Django)最佳導入實踐

from foo.bar import MyClass 

不導入正常情況下,或者除非你知道自己在做什麼MyClass的首選方式。 (更確切地說,一個更好的辦法想:

import foo.bar as foobaralias 

,然後在代碼中,訪問MyClass的使用

foobaralias.MyClass 

總之,似乎上述引用鏈接說這是通常更好地導入從模塊,而不是隻是部分模塊的一切。

但是,我鏈接的那篇文章真的很老。

我也聽說,至少在Django項目的上下文中,反而只導入要使用的類,而不是整個模塊更好。據說這種形式有助於避免循環導入錯誤,或者至少使django導入系統更脆弱。有人指出,Django自己的代碼似乎更喜歡「從x導入y」到「導入x」。

假設我正在處理的項目沒有使用__init__.py的任何特殊功能...(我們的所有__init__.py文件都是空的),我應該使用哪種導入方法,爲什麼?

回答

5

對於我來說,這是依賴於局勢。如果它是一個唯一命名的方法/類(即不是process()或類似的東西),並且您打算使用它,那麼保存輸入並只需執行from foo import MyClass

如果要從一個模塊導入多個東西,最好只導入模塊,並執行module.bar, module.foo, module.baz等,以保持名稱空間的清潔。

您也說

有人說,這種形式有助於避免循環導入錯誤或至少使Django的導入系統不那麼脆弱。有人指出,Django自己的代碼似乎更喜歡「從x導入y」到「導入x」。

我不明白這種方式或其他方式如何防止循環導入。原因是,即使在做from x import y,導入所有x。只有y被帶入當前命名空間,但整個模塊x都被處理。試試下面這個例子:

在test.py,把下面的:

def a(): 
    print "a" 

print "hi" 

def b(): 
    print "b" 

print "bye" 

然後在 'runme.py',就把:

from test import b 

b() 

然後就去做python runme.py

您將看到以下輸出:

hi 
bye 
b 

因此,即使您只導入了b

2

後者的優點是MyClass的起源更加明確。前者將MyClass放入當前名稱空間,以便代碼可以僅使用MyClass不合格。所以對於讀MyClass定義的代碼的人來說,這並不那麼明顯。

13

首先,主要的進口規則:永遠不會使用from foo import *

本文正在討論週期性進口問題,該問題目前仍存在於結構不良的代碼中。我不喜歡週期性進口;他們的存在是一個很強的信號,表明某些模塊做得太多,需要分解。如果出於任何原因,您需要使用無法重新安排的週期性進口代碼,import foo是唯一的選擇。

對於大多數情況下,import foofrom foo import MyClass之間沒有太大差別。我傾向於第二種,因爲沒有涉及到更少的輸入,但就是爲什麼我會用第幾個原因:

  • 模塊和類/值有不同的名稱。讀者可能很難記住特定導入來自哪裏,導入的值的名稱與模塊無關。

    • 好:import myapp.utils as utils; utils.frobnicate()
    • 好:import myapp.utils as U; U.frobnicate()
    • 壞:from myapp.utils import frobnicate
  • 你從一個模塊中導入了大量的值。保存你的手指和讀者的眼睛。

    • 壞:from myapp.utils import frobnicate, foo, bar, baz, MyClass, SomeOtherClass, # yada yada
+0

因此,test.py中的所有內容都已運行。對此的特定異常可能在您導入實現模型(表示數據庫表)的類的Django中。在這種情況下,最好說「從django.contrib.auth導入用戶」。但正如我所說,這是一個特定於特定環境的慣例。 – 2009-11-10 03:13:05

+2

從myapp導入utils怎麼樣; utils.frobnicate()'? – Joschua 2010-09-16 09:59:14

+1

Joschua:這很好,因爲任何人都可以看到'frobnicate'從哪裏進口。 – 2010-09-16 17:23:23