2017-08-15 155 views
1

我想將類A的實例的方法foo傳遞給另一個函數run_function。方法foo將使用其類A的實例變量。如何將使用實例變量的實例方法作爲參數傳遞給另一個函數?

這裏是一個最小的例子,其中A的實例變量只是self.a_var,而foo只是打印該變量。

class A: 
    def __init__(self,a_var): 
     self.a_var=a_var 
    def foo(self): 
     print(self.a_var) 


class B: 
    def __init__(self, A): 
     self.A=A 

     # EDIT (comment to compile) 
     self.A.do_something() 

    def run_function(self): 
     self.A.foo() 
    def run_function_2(self, bar): 
     bar() 



myA = A(42) 
myA.foo() 

# Current implementation 
myB=B(myA) 
myB.run_function() 

# Better(?) implementation 
myB.run_function_2(myA.foo) 

目前,我A類的實例myA傳遞到的B實例和顯式調用self.A.foo()。這會強制A的功能名稱爲foo。這是愚蠢的。

更好的(?)實現將實例的功能傳遞給run_function2。這有效,但我不確定這是否「安全」。

問:

有沒有,我不此刻看到任何漏洞?

重要的部分是傳遞的方法foo需要訪問(它的)類實例的實例變量。那麼,在run_function_2裏面調用的foo總是可以訪問所有的實例變量myA

有沒有更好的實現方法?

編輯:我忘了補充說,class B將始終有一個A的實例,因爲它必須與該實例do_something。也許這會改變某些東西(?)。抱歉!

+0

澄清,當你說「保存」時,你的意思是「安全」嗎? – Miket25

+0

@ Miket25 Urg,是:/ –

回答

1

對於你的第二個實現,你有沒有考慮以下幾點:

>>> myAa = A(42) 
>>> myAb = A(43) 
>>> myB = B(myAb) 
>>> myB.run_function_2(myAa.foo) 
42 

這可能不是你想要的。如何使用getattr(),只是傳遞所需的方法名稱:

>>> class C: 
...  def __init__(self, A): 
...    self.A = A 
...  def run_fct(self, bar): 
...    fct = getattr(self.A, bar) 
...    fct() 
... 
>>> myC = C(myAa) 
>>> myC.run_fct('foo') 
42 
+0

感謝您的回答。事實上,這個「43」這個問題是一個很好的觀點。關於'getatrr':我必須玩這個功能並閱讀它,看看它的潛力。我以前從未使用過。它最終擺脫了「43」組織。 –

+0

@P.Siehr在更復雜的情況下,我可以想象「43」問題甚至導致一些非常討厭的調試會話,因爲傳遞錯誤實例的方法可能很難找到,所以我肯定會強烈建議該方法。 – bgse

1

回答您的問題:

  1. 在一個對象實例的上下文中執行任何功能將有機會獲得實例變量。
  2. 可能有更好的方法來實現這一點,你可以嘗試爲類A和其他可能類似的類定義一個接口。你知道這個函數總是被稱爲foo()。如果沒有,我會問爲什麼你需要有一個對象調用另一個對象的任意方法。如果你可以給出更多具體的例子來說明你正在嘗試做什麼,這將會有所幫助。
+0

感謝您的回答。作爲一名數學家,我儘可能抽象,不要惹惱任何細節。也許不是最好的選擇;) ----'B'類是我稱之爲'CrashHandler'的東西。它會在幾天內調用'foo'幾次(> 100次)。如果'foo'拋出一個錯誤,'CrashHandler'會抓住它,做很多事情(清理),然後再次調用'foo'。 「CrashHandler」不是「A」的一部分的原因是,其他用戶將編寫他們自己的類「A」 - 至少是「foo」部分,例如使用繼承。所以'CrashHandler'是他們不應該碰的東西。 –

+0

我建議你實現A類的超類,並提供一個必需的接口,然後可以由所有的子類實現。包含'handle_crash()'和'run()'等方法,例如 – pypypy

+0

我會考慮這個。感謝您的建議。 –

0

run_functionrun_function_2之間的主要區別在於,前者電話foo這是考慮到B()構造的對象。 run_function_2獨立於將對象保存爲self.A;它只是調用你給它的函數/方法。例如

class A: 
    def __init__(self,a_var): 
     self.a_var=a_var 
    def foo(self): 
     print(self.a_var) 


class B: 
    def __init__(self, A): 
     self.A=A 
    def run_function(self): 
     self.A.foo() 
    def run_function_2(self, bar): 
     bar() 

myA = A(42) 
myB = B(myA) 
myA2 = A(3.14) 

myB.run_function() 
myB.run_function_2(myA.foo) 
myB.run_function_2(myA2.foo) 

輸出

42 
42 
3.14 

有沒有,我不此刻看到任何漏洞?

這兩種調用方法都很好。雖然我同意function_run_2更方便,因爲它不修複方法名稱,但它使您問......如果從未使用過,將A對象放在B構造函數中的目的是什麼?

重要的部分是,傳遞的方法foo需要訪問(它的)類實例的實例變量。那麼,在run_function_2中調用的foo是否總是可以訪問myA的所有實例變量?

是的。 run_function_2參數需要一個函數。在這種情況下,您通過myA.foo,對象myA的方法在class A中定義。當您在run_function_2中調用foo時,您只處理實例myA的屬性變量;這是封裝在類中的想法。

有沒有更好的方法來實現這個?

回答您的安全問題,這是完全安全的。函數和方法是Python中的對象,它們可以像值一樣傳遞。你基本上依賴於函數壓縮或部分函數的想法。請參閱How do I pass a method as a parameter in Python。這兩種方式都很好。

相關問題