2013-01-21 7 views
1

比方說,我們有以下類別:這種將鴨子打字與isinstance()混合在一起的方法是否合理?

class Duck(object): 
    pass 

class OldFashionedDuck(Organism, Duck): 
    def look(self): 
     self.display_biological_appearance() 
    def walk(self): 
     self.keep_balance_on_two_feet() 
    def quack(self): 
     self.make_noise_with_lungs("Quack!") 

class ArtificialDuck(Robot, Duck): 
    def look(self): 
     self.display_imitation_biological_appearance() 
    def walk(self): 
     self.engage_leg_clockwork() 
    def quack(self): 
     self.play_sound("quack.au") 

在這個例子中,OldFashionedDuck和ArtificialDuck沒有共同的實現,而是通過建設他們都將用於isinstance(...,鴨)返回True。

這並不完美,但它是我認爲可能有助於尊重鴨子打字和(通過空的mixin繼承)allow isinstance()的東西。實質上,它提供了一個契約來滿足一個接口,所以它不是基於完成所有工作的類來調用isinstance(),而是基於任何人都可以選擇的接口。

我看過基於「isinstance()被認爲有害的文章」,因爲它打破了鴨子的打字。然而,至少我作爲一個程序員想知道,如果不一定是一個對象從哪裏獲取函數,但是它是否實現了一個接口。

這種方法是否有用,如果有的話可以改進?

+1

您不清楚如何或爲什麼要使用'isinstance()'。這使得很難解決這是否是正確的事情。 –

+0

[抽象基類](http://www.python.org/dev/peps/pep-3119/)會爲此工作嗎? –

回答

6

我看過基於「isinstance()被認爲有害的文章」,因爲它打破了鴨子的打字。然而,至少我作爲一個程序員想知道,如果不一定是一個對象從哪裏獲取函數,但是它是否實現了一個接口。

我認爲你錯過了這一點。

當我們談論「鴨子打字」時,我們真正的意思是沒有形式化我們的接口。因此,你試圖做的事情歸結爲試圖回答「我怎樣才能使我的界面形式化,同時還沒有形式化我的界面?」。

我們期待一個給我們實現一個接口的對象 - 我們描述的一個接口,不是通過創建一個基類,而是通過編寫一堆文檔和描述行爲(如果我們感覺特別活潑,設置某種測試套件) - 因爲我們說這是我們期望的(再次在我們的文檔中)。我們通過嘗試像使用它一樣來驗證對象是否實現了接口,並將任何由此產生的錯誤視爲調用方的責任。調用給我們錯誤對象的代碼是調皮的,這就是錯誤需要修復的地方。 (同樣,測試幫助我們跟蹤這些事情了。)

總之,測試isinstance(this_fuzzball_that_was_handed_to_me, Duck)並沒有真正幫助的事項:

  • 它可以通過isinstance檢查,但實現的方式方法是違反了我們的預期(或者說,return NotImplemented)。這裏只有真正的測試。

  • 它可以通過檢查,但實際上完全無法實現一個或多個方法;畢竟,基地Duck不包含任何實現,並且Python沒有理由在派生類中檢查它們。

  • 也許更重要的是,它可能會失敗,即使它是一個完全可用的鴨子模糊球。也許這是一個不相關的對象,其具有quackwalklook直接功能,手動附加到它作爲屬性(而不是它的類的屬性,它們成爲查找時變成方法)。

好吧,那麼,「不要那樣做」,你說。但現在你爲每個人做更多的工作;如果客戶不要總是選擇加入,那麼對於使用鴨子的代碼進行檢查是沒有用的和危險的。與此同時,你獲得了什麼?

這與EAFP的原理有關:不要試圖通過查看它是否是鴨子;如果它是一隻鴨子,把它當作一隻鴨子來處理,如果它不是,則應該處理血腥的混亂。


但是,如果你不關心鴨打字理念,絕對必須強制嚴謹一些外表上的東西,你可能會感興趣的標準庫abc模塊中。

1

儘管我不想高估這個術語,但是:您的方法不是pythonic。做鴨子打字,或者不要做。

如果你想確保你的「接口」實現實現它的一切應該:測試它!

對於較小的項目,很容易記住您需要什麼。你可以簡單地嘗試它。

我同意,對於大型項目,甚至團隊合作,最好確保您的類型具有所需的一切。在這種情況下,你絕對應該使用單元測試來確保你的類型是完整的。即使沒有鴨子打字,你也需要測試,所以你可能不需要任何額外的測試。

Guido van Rossum在this talk中提到了一些關於鴨子打字的有趣想法。這非常鼓舞人心,絕對值得一看。

相關問題