2011-12-21 57 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

相關問題