2010-07-30 73 views
12

關於使用__call__的民意是什麼?我只是很少見到它使用過,但我認爲這是一個非常方便的工具,當你知道某個類將被用於某些默認行爲時。什麼時候正在使用__call__一個好主意?

+1

-1:這不是一個「意見」問題。事情並不「方便」。這只是**需要**來製作**可調用對象**。 – 2010-07-30 11:07:00

+0

這個問題更關注於何時有可調用的對象。 '__call__'方法只是實現這一目的的手段。我對行爲比對實現行爲的機制更感興趣。如果你想要把問題投下來,那麼你應該用箭頭按鈕來做,而不是你的評論。 – 2010-07-30 11:30:17

+1

通過評論指出爲什麼某個帖子被拒絕並且該帖子是否可以改進通常被認爲是禮貌的。當然,假設評論是_politely_。 – 2010-07-30 16:54:55

回答

15

我認爲你的直覺是正確的。

歷史上,可以調用的對象(或者我有時聽到的稱爲「函子」)已經被OO世界用來模擬閉包。在C++中,它們通常是不可或缺的。

然而,__call__有相當多的在Python世界中的競爭:

  • 定期命名的方法,其行爲有時可能會出現很多更容易從名字上判斷。可以轉換爲綁定方法,可以像函數一樣調用。
  • 閉包,通過返回嵌套塊中定義的函數而獲得。
  • 拉姆達,這是一種有限但快速的封閉方法。
  • 發電機和協同程序,它們的身體像一個仿函數一樣具有累積狀態。

我會說使用__call__的時間是當你沒有更好地服務的上述選項之一。檢查以下標準,也許:

  • 您的對象有狀態。
  • 你的班級有一個明顯的「主要」行爲,名字很傻。例如。如果您發現自己正在編寫run()doStuff()go()或者廣受歡迎且永久冗餘的doRun(),您可能會有應聘者。
  • 您的對象的狀態超出了生成器函數的期望值。
  • 您的對象包裝,模擬或抽象函數的概念。
  • 您的對象有其他輔助方法,它們在概念上屬於您的主要行爲。

我喜歡的一個例子是UI命令對象。設計的目的是讓他們的主要任務是執行comnand,但使用額外的方法來控制它們的顯示爲一個菜單項,例如,這對我來說似乎是你仍然想要一個可調用對象的東西。

4

,如果你需要你的對象可以被調用使用它,這就是它的存在是有

我不知道你的默認行爲意味着

一個使用時我發現了它特別有用的是什麼一個包裝器或某些對象在某個框架/庫內被調用的深處。

+0

Urgh。問題現在看起來非常愚蠢。默認行爲我的意思是,雖然類通常有幾種方法,但通常有一個非常規則的從數據輸入到數據輸出的工作流程。我想知道是否可以使用__call__來提高訪問標準工作流的速度。 – 2010-07-30 08:15:41

+0

好一點。我不確切地知道你的意思是「提高訪問標準工作流程的速度」。 '__call__'通常與速度無關。如果你使用'obj()'而不是像'obj.function_name()'這樣的東西,你可以保存一個屬性查找,但這並不值得一提。 – nils 2010-07-30 08:30:49

+0

@Tim McNamara:正確。問題很愚蠢。特別是它的「意見」部分。 – 2010-07-30 11:08:13

1

更一般地說,Python有雙下劃線方法的lot。他們在那裏是有原因的:他們是Python重載操作符的方式。例如,如果你想要一個新的類,其中,我不知道,打印"foo",你定義__add____radd__方法。對此,沒有任何好處或壞處,比使用for循環有什麼好處或壞處。

事實上,使用__call__通常是Pythonic的方法,因爲它鼓勵代碼的清晰。比如說,你可以用MyCalculator(foo)代替MyCalculator.calculateValues(foo)

+0

它是MyCalculator(foo)還是theCalculatorObject(foo)? – Nabin 2017-12-29 08:41:09

0

它通常在類用作一些實例上下文的函數時使用,比如一些DecoratorClass將被用作@DecoratorClass('some param'),所以'some param'將被存儲在實例的名字空間中,然後實例被調用爲實際的裝飾器。

當你的類提供了一些不同的方法時,它並不是非常有用,因爲它通常並不明顯,調用會做什麼,在這些情況下顯式比隱式更好。

相關問題