2011-12-21 45 views
1

我有2个模块,每个模块都包含一个类。
我的主程序实例化了一个类的对象,它实例化了许多类的对象。
我需要能够从第二类的实例中调用第一类函数。
这是什么,我有一个大致的样子:如何在python中调用实例创建者的函数?

模块mod_one.py:

import mod_two 

class One: 
    def __init__(self): 
     self.new_instance = Two() 

    def call_back_func(self): 
     # This function should be called 
     # from the new instance of class Two() 

模块mod_two.py:

class Two: 
    def __init__(self): 
     # Call call_back_func() of module mod_one 

我发现的唯一途径是通过回调函数call_back_func()作为第二类的参数,如下所示:

self.new_instance = Two(self.call_back_func) 

但我想知道是否有更好的方法来做到这一点。

+3

这是一个非常有效的方法,因为它不会引入循环依赖。 – 2011-12-21 18:29:15

+0

我认为将'self.call_back_func'传递给构造函数是一个很好的方法。 – NPE 2011-12-21 18:29:17

回答

1

你在做什么是完全有效的。请注意,__init__不是构造函数。它是只是的一种初始化方法。 (__new__是Python的构造函数方法)

更多关于这个话题可以讨论Python's use of __new__ and __init__?

+0

-1:我无法看到'__init__'与其他语言的构造函数的概念不同。 '__new__' OTOH是一种在Java/C++等语言中不存在的概念,所以我不明白怎么说它更适合这个概念。我认为“'__init__'不是构造函数”是一个神话,并且是一个毫无帮助的。官方的python文档甚至提到'__init__'作为构造函数! http://docs.python.org/reference/datamodel.html#basic-customization – Ben 2011-12-21 20:44:27

+0

对象构造在离开__new__时完成... – gecco 2011-12-21 21:01:52

+0

在输入构造函数之前,它向成员分配值。正如在Java和C++中一样。唯一的区别是它们不提供像'__new__'这样的工具来自定义新实例的过程。 – Ben 2011-12-21 21:11:07

0

我觉得你在这里失踪的对象被发现。具体的Creational Builder Pattern

class OneTwoBuilder: 

    def createOne(self, num_of_two=0): 
     o = One() 
     child = [] 
     for _ in xrange(num_of_two): 
      t = Two() 
      o.callback(t) 
      child.append(t) 
     o.setChilds(child) 
     return o 
2

我觉得有一个权衡这里简单性和松耦合之间。在我看来,简单性就是将回调传递给一个对象,而松耦合则是使用一个框架在对象之间传递信号。

举例来说,如果你使用blinker信号库,您可以使用此替代设计:

from blinker import signal 

class One: 
    def __init__(self): 
     self.two = Two() 
     self.two.some_signal.connect(self.callback) 

    def callback(self, data): 
     print 'Called' 

class Two: 
    some_signal = signal('some_signal') 

    def process(self): 
     # Do something         
     self.some_signal.send() 

one = One() 
one.two.process() 

在上面的代码中,Two对象甚至不知道是否有其他物体关心其内部状态改变。但是,它通过发出可能被其他对象使用的信号(在本例中为One对象)来执行某些特定操作来通知它们。

这种方法的一个很好的例子是GUI框架。当一个按钮小部件被创建时,不需要传递一个回调,该按钮被点击时应该被执行。然而,该按钮发出点击信号,并且无论订阅哪个回调信号都被执行以执行期望的动作。

+0

谢谢,我会试试看,尽管上面的评论鼓励我“不修复它如果它没有坏“:) – user1102018 2011-12-21 20:05:35

+0

我同意这些意见,我相信你只需要知道其他的替代方案,以防万一以后你发现你传递了太多的回调。 – jcollado 2011-12-21 20:21:58

+0

我来这里用blinker来说明如何在发出信号时如何调用对象的方法。我发现你的例子非常有用,谢谢。 – Jabba 2013-06-28 15:28:32

相关问题