2016-07-26 50 views
0

我有一個包含多個子文件夾的項目,其中大部分都是Python包。其中一個包含一個名爲BaseStep的抽象類(使用abc模塊創建),在運行時期間使用以下代碼查找自己的子類:for subclass in cls.__subclasses__(): ...BaseStep位於pipeline目錄中,位於名爲base_step.py的python文件中,因此通過執行pipeline.base_step.BaseStep來訪問。Python不識別子類,除非它被導入__init__.py

這個包看起來像:

pipeline/ 
    __init__.py 
    base_step.py 

在另一個Python包,我想創建如何使用BaseStep一些例子。這個包叫做examples,我有一個叫做sample_step.py的python文件。在sample_step.py之內,我創建了一個擴展名爲SampleStep的類BaseStep。因此通過做examples.sample_step.SampleStep來訪問它。

這個包看起來像:

examples/ 
    __init__.py 
    sample_step.py 

當我嘗試在運行時訪問__subclasses__(),但是,我看不到SampleStep列爲其中之一。

的唯一途徑SampleStep顯示爲的BaseStep一個子類是,如果pipeline目錄的__init__.py包括SampleStep的進口:

from examples.sample_step import SampleStep 

爲什麼會出現這種情況?爲什麼我必須在管道包內輸入我的樣品步驟?爲什麼BaseStep不能識別其他軟件包中的子類?任何幫助理解繼承和導入將深受讚賞。


編輯

感謝您的意見。從評論中,我意識到我沒有解釋如何導入SampleStep,並刪除了我對評論的一些迴應。

examples模塊實際上是這樣的:

examples/ 
    __init__.py 
    runner.py 
    sample_step.py 

初始化的.py,我有from examples.sample_step import SampleStep。然後我打電話runner.py,它通過調用BaseStep中的函數實例化SampleStep,該函數查看其子類。至少這是它試圖去做的 - 它失敗了,因爲BaseStep沒有意識到SampleStep是一個子類。

@Blckknght說:「你可以從任何地方導入模塊(只要該」任何地方「正在加載本身)」。所以更具體的問題是:爲什麼在運行時BaseStep沒有在examples/__init__.py內導入SampleStep來識別它是一個子類?

+0

調用「BaseStep」中爲cls .__子類__():定位子類的部分的代碼在哪裏? – jwodder

+0

爲子類調用BaseStep的代碼位於'pipeline'的同一個包中。 – user2226006

回答

2

SampleStep子類不存在直到其文件被導入。

3

Python是一種動態語言。像類定義在技術上是在運行時發生的,而不是像C和Java之類的其他語言中的一些早期編譯時。這意味着,除非導入sample_step模塊並運行其SampleStep類的定義,否則就Python解釋器而言,該類不存在。

您可以從任何地方導入模塊(只要該「任何地方」正在加載本身)。它只需要加載一次子類以顯示在BaseStep.__subclasses__列表中。