2016-07-26 62 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__列表中。