這篇文章主要介紹了Python類別的動態修改的實例方法的相關資料,需要的朋友可以參考下
Python類別的動態修改的實例方法
相信很多朋友在程式設計的時候都會想修改一下已經寫好的程式行為程式碼,而最常見的方式就是透過子類別來重寫父類別的一些不滿足需求的方法。比如說下面這個例子。
class Dog: def bark(self): print 'Woof!' class Husky(Dog): def bark(self) print 'Howl!'
我們可以用上述方式來修改我們自己寫的程式碼,但是我們該怎麼修改第三方程式碼呢?當然,我們也可以自己寫一個子類,呼叫子類別的實例物件來實作修改,但是這樣可能會引入其他一系列問題。所以我們得想個辦法用我們自己的方法替換掉原來的物件方法,這就是本文接下來要介紹的「打補丁」的方式。
給類別打補丁
如果我們想新增或是修改物件的方法的話,最簡單的方式莫過於給類別打個補丁了。結合上面的例子,如果我們想給我們自己的Dog 類別寫一個新的howl 方法的話,我們可以定義一個新的howl 函數,像下面的程式碼一樣把它加到我們的類別中:
def newbark(self): print 'Wrooof!' def howl(self): print 'Howl!' # Replace an existing method Dog.bark = newbark # Add a new method Dog.howl = howl
很簡單吧?但是這裡有幾個問題需要我們注意。首先,被修改的類別的所有實例中的方法都會被更新,所以更新後的方法不僅僅存在於新創建的物件中,之前創建的所有物件都會擁有更新之後的方法,除非只是新增而不是覆蓋掉原來的方法。第二,你修改或新增的方法應當是與物件綁定的,所以方法的第一個參數應該是被呼叫的物件(這裡就是類別的實例self)。
給類別實例打補丁
單一物件也可以在不影響這個類別的其他實例的情況下打補丁。但還是有點小技巧的!先讓我們來看看下面這個例子。
def herd(self, sheep): self.run() self.bark() self.run() border_collie = Dog() border_collie.herd = herd
然後我們再試試呼叫新定義的方法:
border_collie.herd(sheep) TypeError: herd() takes exactly 2 arguments (1 given) The problem with the previous code is that the herd is not a bound method, just take a look at the following code: print border_collie.herd <function herd at 0xf9c5f0>
出錯啦!引發錯誤的原因就是被呼叫的物件並沒有作為第一個參數傳給我們寫的函數。當然我們可以自己把參數傳進去,但是在這個替換類別方法的場景下並不奏效。解決這個問題的正確方案是用 type 這個模組裡的 MethodType 函數,我們可以看看下面的範例程式碼:
import types border_collie = Dog() border_collie.herd = types.MethodType(herd, border_collie) print border_collie.herd <bound method ?.herd of <__main__.Dog instance at 0x23c9518>> border_collie.herd(sheep)
現在我們的方法已經和實例綁定了,大功告成!
總結
運行中替換或添加方法是非常有用的,比如說在單元測試中,有些負責和外界服務通訊的函數就需要替換掉,方便測試。這個技巧不僅很常用,而且在你最終決定要修改程式碼之前還可以保持程式碼的可維護性,是一個非常重要的技巧。
以上是解析Python類別的動態修改的實例程式碼的詳細內容。更多資訊請關注PHP中文網其他相關文章!