2013-01-06 18 views
1

我可以使這個代碼工作,但我仍然困惑爲什麼它不會以我嘗試的第一種方式工作。從python中的另一個文件導入類 - 我知道修正,但爲什麼不是原來的工作?

我正在練習python,因爲我的論文將被編碼(使用Arduino和PC界面來做一些很酷的事情)。我試圖從另一個文件導入一個類到我的主程序,以便我可以創建對象。這兩個文件都在同一個目錄中。如果您現在查看代碼,可能會更容易。

#from ArduinoBot import * 
#from ArduinoBot import ArduinoBot 
import ArduinoBot 

# Create ArduinoBot object 
bot1 = ArduinoBot() 

# Call toString inside bot1 object 
bot1.toString() 

input("Press enter to end.") 

這是非常基本的ArduinoBot類

class ArduinoBot: 

def toString(self): 
    print ("ArduinoBot toString") 

無論是前兩個註釋掉的import語句將會使這項工作,但不是最後一個,這對我來說似乎是最直觀,最普遍。在這裏沒有很多代碼出錯,當我聽到關於Python的許多好東西時,碰到這種尖銳的語言特定怪癖有點令人沮喪。無論如何,我必須做錯了什麼,但爲什麼不簡單的'導入ClassName'或'導入FileName'工作?

謝謝你的幫助。在你的主程序

class foo(object): 
    pass 

class bar(object): 
    pass 

class example(object): 
    pass 

現在,如果你這樣做:

+0

實際上'導入FileName'的作品,只要文件在你的$ PYTHONPATH。 – adamsmith

+1

這根本不是「挑剔的」。在第一種情況下,您將模塊的整個名稱空間導入本地名稱空間。在第二種情況下,您將模塊名稱空間中的一個類導入到本地名稱空間中。第三,您將模塊本身導入到本地名稱空間,因此,您必須以其成員身份訪問其成員。如果你沒有像你的類一樣命名你的文件(這真的是Java的東西),或許就像'arduino_lib',那麼它可能會更清晰。 –

+1

@ sr2222 - 我通常在它們所在的模塊之後避免命名類,但是至少有一個stdlib模塊('datetime')有先例。 – mgilson

回答

5

考慮文件(example.py

import example 

又該文件example.py進口?只有班級examplefoo也應該出現嗎?如果import module將整個模塊的名稱空間直接拖到當前名稱空間中,則含義太模糊。

這個想法是命名空間是美好的。他們讓你知道類/函數/數據來自哪裏。他們還讓你把相關的東西組合在一起(或者等價地,它們可以幫助你把不相關的東西分開!)。一個模塊設置了一個名稱空間,並通過您使用import的方式告訴python您想如何將該名稱空間帶入當前上下文(名稱空間)。

from ... import *表示 - 將該模塊中的所有內容直接放入我的名稱空間中。

from ... import ... as ...說,只把我指定的東西直接帶到我的名字空間,但在這裏給它一個新的名字。

最後,import ...只是說把這個模塊放到當前的命名空間中,但要保持它的獨立性。由於(至少)2個原因,這是生產代碼中最常見的形式。

  • 它可以防止名稱衝突。你可以有一個名爲foo局部類,不會與fooexample.py衝突 - 你可以通過example.foo
  • 它可以很容易地跟蹤下來哪個模塊中的一類,從調試來獲得訪問該。

考慮:

from foo import * 
from bar import * 
a = AClass() #did this come from foo? bar? ... Hmmm... 

在這種情況下,從example.py獲取到類example訪問,你也可以這樣做:

import example 
example_instance = example.example() 

,但你也可以得到foo

foo_instance = example.foo() 
+0

我想這只是一種不同的思考方式 - 對我來說,導入FileX意味着我想從該文件導入所有類。如果他們想要明確,但這不是一個大問題,至少我明白爲什麼現在不工作。謝謝。來自python('import this')的禪宗的 – user1262553

+0

:「顯式比隱式更好」。如果你想隱式,使用'from ... import *'。每種形式的進口都是不同的 - 如果2種形式做了同樣的事情,那也會與禪宗產生衝突(「應該有一種 - 最好只有一種 - 明顯的做法」)。雖然, 「起初,這種方式可能並不明顯,除非你是荷蘭人。」 ;-) – mgilson

+1

爲什麼這有意義?模塊本身是一個對象,是「模塊」類的一個實例。如果導入一個模塊導入了它的所有組件,那麼你將會放棄模塊本身的對象性的許多好處。 –

0

導入不起作用,你認爲它確實如此。它工作是記錄在案的工作方式,因此有對你的問題的一個非常簡單的補救措施,但還是:

import ArduinoBot 

這看起來對進口路徑上的模塊(或包),執行模塊代碼放在新的名稱空間中,然後將模塊對象本身綁定到當前名稱空間中的名稱ArduinoBot。這意味着ArduinoBot模塊中名爲ArduinoBot的模塊全局變量現在可以在導入名稱空間中作爲ArduinoBot.ArduinoBot訪問。

from ArduinoBot import ArduinoBot 

這載荷並如上所述執行的模塊,但模塊對象不結合到名稱ArduinoBot。而是在模塊內查找模塊全局變量ArduinoBot,並綁定當前名稱空間中引用名稱ArduinoBot的任何對象。

from ArduinoBot import * 

與上述類似,這會加載並執行模塊,而不將模塊對象綁定到當前名稱空間中的任何名稱。然後它會查找全部模塊全局變量,並將它們全部綁定到當前名稱空間中的相同名稱。

最後的形式是在Python Shell交互工作很方便,但一般認爲是不好的風格在實際開發中,因爲它不是清楚什麼名字,它實際上結合。考慮到它進口一切全球進口模塊中,包括在全球範圍內引進任何名字,它很快變得非常難以知道是什麼名字的範圍或他們來自何處,如果你使用普遍地這種風格來了。

0

簡單的答案是模塊是Python中的東西。模塊作爲類,函數和其他對象的容器具有自己的狀態。當您執行import ArduinoBot時,您將導入模塊。如果你想要那個模塊中的東西 - 類,函數等 - 你必須明確地說你想要它們。您可以直接使用from ArduinoBot import ...導入它們,也可以通過模塊import ArduinoBot然後ArduinoBot.ArduinoBot訪問它們。

,而不是針對這方面的工作,你應該利用模塊的容器的煩躁,讓您將相關材料到模塊。當你在一個文件中只有一個類時,看起來似乎很煩人,但是當你開始在一個文件中放入多個類和函數時,你會發現當你做import module時,你實際上並不希望所有的東西都被自動導入,因爲那麼來自所有模塊的所有內容都會與其他事物相沖突這些模塊在分離不同功能方面提供了有用的功能。

對於你的例子,你應該問自己的問題是:如果代碼非常簡單和緊湊,爲什麼不把它全部放在一個文件中?

0

模塊本身是一個對象。如果您作爲模塊的成員訪問您的課程,最後一種方法確實可行。無論是如果下面的工作,並且要麼可能是適當的,這取決於你從進口商品需要些什麼:

from my_module import MyClass 
foo = MyClass() 

import my_module 
foo = my_module.MyClass() 

正如在評論中提到,你的模塊和類通常在Python中沒有相同的名稱。這更像是一件Java事情,有時可能會導致一些混亂。

相關問題