2016-12-06 35 views
3

看來,使用兩個不同的進口實體PYTHONPATH s是而不是相同的對象。從兩條不同路徑導入的類是不相等的?

我在我的代碼中遇到了一個小問題,我想用一個小測試用例來解釋它。

我創建的源代碼樹:

a/ 
    __init__.py 
    b/ 
    __init__.py 
    example.py 

在example.py:

class Example: 
    pass 

,並從文件夾a的父母,我運行Python和這個測試:

>>> import sys 
>>> sys.path.append("/home/marco/temp/a") 
>>> 
>>> import a.b.example as example1 
>>> import b.example as example2 
>>> 
>>> example1.Example is example2.Example 
False 

所以問題是:爲什麼結果是False?即使通過兩條不同路徑導入,類也是一樣的。如果這個類是一個自定義的異常,並且你試圖用except來捕捉它,這是一個完全的混亂。

測試用蟒3.4.3

回答

2

在Python中,class語句是一個可執行文件聲明,所以每次執行它時,都會創建一個新類。

當您導入模塊時,Python將檢查sys.modules以查看指定路徑上的模塊是否已存在。如果確實如此,那麼您將只返回相同的模塊,否則它將嘗試加載模塊並執行其包含的代碼。

因此,到同一模塊的兩條不同路徑將加載代碼兩次,這會執行兩次語句class,並且您將獲得兩個定義的獨立類。

當他們有一個文件a.py時,它們通常會碰到人,他們將其作爲腳本運行,然後在另一個模塊中嘗試導入a。該腳本加載爲__main__,因此具有與導入的模塊不同的類和不同的全局變量。

道德是,在參考模塊的過程中始終保持一致。

+0

'當你導入一個模塊時,Python會檢查sys.modules,看看在指定路徑上的模塊是否已經存在。問題是真正的模塊路徑確實是一樣的,它的'PYTHONPATH'不同。由於我使用python3不允許輸入''',我認爲真正的路徑可以而且應該被檢查。 –

+1

不是文件路徑,模塊路徑,即此處爲'a.b.example'或'b.example'的模塊的名稱。兩個不同的名稱,兩個不同的模塊。 – Duncan

0

is的操作者使用,以檢查是否兩個名字都指向相同的對象(存儲位置)。

example1.Example is example2.Example 

顯然不是指向相同的位置,因爲您導入了相同的對象兩次。

但是,如果你不喜歡的東西:

a, b = example1.Example, example1.Example 

a is b # True 

相反,你應該使用==操作:

example1.Example == example2.Example 
True 

需要注意的是,如果你不執行__eq____hash__,默認行爲與is

+0

你試過嗎?即使兩個類的定義相同,兩個類的平等比較也會返回「False」。對於一個類來說=='通常和'is'是完全一樣的(儘管我猜你可以用一個元類覆蓋這個行爲,但那是不尋常的)。 – Duncan

+0

@Duncan是的,如果你沒有實現'__eq__'或'__hash__'默認行爲與 – user312016

+0

@Duncan相同如果情況總是如此,因爲所有東西都是python中的對象,所以'=='會起作用不求回報。 – user312016

相關問題