2010-06-30 48 views
0

我遇到了循环导入问题。我有三个Python测试模块:robot_test.py,它是我的主脚本,然后是两个辅助模块,controller_test.py和servo_test.py。我的想法是,我希望controller_test.py为我的微控制器定义一个类,为servo_test.py定义一个类来定义我的舵机。然后我想在robot_test.py中实例化这些类。这里是我的三个测试模块:如何避免在Python中导入循环?

""" robot_test.py """  
from pi.nodes.actuators.servo_test import Servo 
from pi.nodes.controllers.controller_test import Controller 

myController = Controller() 
myServo = Servo() 

print myController.ID, myServo.ID 


""" controller_test.py """ 
class Controller(): 
    def __init__(self, id="controller"): 
     self.ID = id 


""" servo_test.py """ 
class Servo(): 
    def __init__(self, id="servo"): 
     self.ID = id 

如果我跑robot_test.py,我得到预期的打印输出:

控制器伺服

然而,现在来的扭曲。实际上,servo_test.py模块通过robot_test.py的方式依赖于controller_test.py。这是因为我的伺服定义在它们自己被实例化之前需要一个已经实例化的控制器对象。但我想保留robot_test.py中的所有初始实例。所以,我想修改我servo_test.py脚本如下:

""" servo_test.py """ 
from pi.nodes.robots.robot_test import myController 
class Servo(): 
    def __init__(self, id="servo"): 
     self.ID = id   
     print myController.ID 

当然,我能感觉到圆是要引起问题果然,当我现在尝试运行robot_test.py我得到的错误:

导入错误:无法导入名称伺服

这又是servo_test.py返回错误引起的:

导入错误:无法导入名myController的

在C#中我将myController和myServo定义为robot_test.py中的静态对象,然后我可以在其他类中使用它们。无论如何,在Python中做同样的事情吗?我找到的一种解决方法是将myController对象作为参数传递给Servo类,但我希望避免必须这样做。

谢谢!

+0

你不喜欢将控制对象作为参数传递给你? – MattH 2010-06-30 14:18:27

+0

我很高兴使用这个解决方案,如果它是唯一可用的,但我想尽可能地扩展我对Python的理解,所以想知道是否有其他方法来做到这一点。 – RPG 2010-06-30 14:27:22

+0

首先,搜索SO作为“循环导入”。 http://stackoverflow.com/search?q=python+circular+import其次,阅读这些问题,看看其中哪些与您的相同。 – 2010-06-30 15:26:05

回答

0

servo_test.py实际上并不需要需要myController,因为访问是在一个函数内。改为导入模块,并通过该模块访问myController

import pi.nodes.robots.robot_test as robot_test 
class Servo(): 
    def __init__(self, id="servo"): 
     self.ID = id   
     print robot_test.myController.ID 

这只要Servo进行实例化之前myController存在工作。

0

将实例化的控制器对象作为init参数传递给Servo的实例化。

""" servo_test.py """ 
class Servo(): 
    def __init__(self,controller,id="servo"): 
     self.ID = id 
     self.ctrl = controller 
     print self.ctrl.ID 

""" robot_test.py """  
from pi.nodes.actuators.servo_test import Servo 
from pi.nodes.controllers.controller_test import Controller 

myController = Controller() 
myServo = Servo(myController) 
+0

“我找到的一种解决方法是将myController对象作为参数传递给伺服类,但我希望避免必须这样做。” – 2010-06-30 14:03:36

+0

哦,我的坏话,当我看到'C#'时,我没有兴趣阅读这篇文章,没想到之后会有什么相关的。 – MattH 2010-06-30 14:17:16

4

One workaround I have found is to pass the myController object to the Servo class as an argument, but I was hoping to avoid having to do this.

究竟为什么你想避免呢?这是一个关键设计模式的经典案例(也许是最重要的一个,它不是原来的四人帮),Dependency Injection。在A的初始化器中具有依赖关系的DI实现方案包括使用设置器方法(其完成另一个关键的非Gof4 DP,two-phase construction,从__init__开始) - 这避免了与进口无关的另一个循环性问题,当A实例需要一个B B的实例需要一个A,在每种情况下,要在逻辑上完成实例“初始化”。但是当你不需要两阶段构造时,初始化器是注入依赖的自然地方。

除了与打破圆形相关的优点外,DI还有助于重用(通过泛化:例如,如果您需要拥有多个控制器和舵机,而不是每个控制器和舵机中的一个,则可以轻松控制“配对”其中包括)和测试(例如,为了测试的目的,通过注入其他模块来容易地隔离每个类)。

不喜欢什么?

+0

+1:Bah ...他说的。我会回去潜伏。 – MattH 2010-06-30 14:32:39

+0

谢谢亚历克斯 - 这就是我一直在寻找的教育! – RPG 2010-06-30 14:35:47