有沒有在Python中重寫實例級別的類方法的方法? 例如:覆蓋實例級別的方法
class Dog:
def bark(self):
print "WOOF"
boby = Dog()
boby.bark() # WOOF
# METHOD OVERRIDE
boby.bark() # WoOoOoF!!
有沒有在Python中重寫實例級別的類方法的方法? 例如:覆蓋實例級別的方法
class Dog:
def bark(self):
print "WOOF"
boby = Dog()
boby.bark() # WOOF
# METHOD OVERRIDE
boby.bark() # WoOoOoF!!
請如圖所示不要這樣做。當您將一個實例與類相區別時,您的代碼變得不可讀。
您無法調試monkeypatched代碼。
當您在boby
和print type(boby)
中發現錯誤時,您會看到(a)它是一隻狗,但(b)出於某種不明確的原因,它不會正確地叫出來。這是一場噩夢。不要做。
請替換。
class Dog:
def bark(self):
print "WOOF"
class BobyDog(Dog):
def bark(self):
print "WoOoOoF!!"
otherDog= Dog()
otherDog.bark() # WOOF
boby = BobyDog()
boby.bark() # WoOoOoF!!
是的,這是可能的:
class Dog:
def bark(self):
print "Woof"
def new_bark(self):
print "Woof Woof"
foo = Dog()
funcType = type(Dog.bark)
# "Woof"
foo.bark()
# replace bark with new_bark for this object only
foo.bark = funcType(new_bark, foo, Dog)
foo.bark()
# "Woof Woof"
class Dog:
def bark(self):
print "WOOF"
boby = Dog()
boby.bark() # WOOF
# METHOD OVERRIDE
def new_bark():
print "WoOoOoF!!"
boby.bark = new_bark
boby.bark() # WoOoOoF!!
可以使用boby
變量的函數裏面,如果你需要的。既然你重寫了這個實例對象的方法,這種方法更簡單,並且與使用self
的效果完全相同。
因爲函數是在Python第一類對象可以通過他們在初始化您的類對象或隨時覆蓋它對於給定的類的實例:
class Dog:
def __init__(self, barkmethod=None):
self.bark=self.barkp
if barkmethod:
self.bark=barkmethod
def barkp(self):
print "woof"
d=Dog()
print "calling original bark"
d.bark()
def barknew():
print "wooOOOoof"
d1=Dog(barknew)
print "calling the new bark"
d1.bark()
def barknew1():
print "nowoof"
d1.bark=barknew1
print "calling another new"
d1.bark()
,結果
calling original bark
woof
calling the new bark
wooOOOoof
calling another new
nowoof
雖然我很喜歡從·洛的傳承理念,與「類型(一)」的東西達成一致,但由於功能也有訪問屬性,我認爲它可以管理這種方式:
class Dog:
def __init__(self, barkmethod=None):
self.bark=self.barkp
if barkmethod:
self.bark=barkmethod
def barkp(self):
"""original bark"""
print "woof"
d=Dog()
print "calling original bark"
d.bark()
print "that was %s\n" % d.bark.__doc__
def barknew():
"""a new type of bark"""
print "wooOOOoof"
d1=Dog(barknew)
print "calling the new bark"
d1.bark()
print "that was %s\n" % d1.bark.__doc__
def barknew1():
"""another type of new bark"""
print "nowoof"
d1.bark=barknew1
print "another new"
d1.bark()
print "that was %s\n" % d1.bark.__doc__
,輸出是:
calling original bark
woof
that was original bark
calling the new bark
wooOOOoof
that was a new type of bark
another new
nowoof
that was another type of new bark
親愛的這不是重寫你只是與對象調用同一個功能的兩倍。基本上,壓倒一切與多於一個班級有關。當相同的簽名方法存在於不同的類中時,那麼您調用的函數決定了調用此函數的對象。在python中覆寫是可能的,當你讓多個類寫入相同的函數,並且有一件事要分享時,Python中不允許重載。
您需要使用類型模塊中的MethodType。 MethodType的用途是覆蓋實例級別的方法(這樣自我可以在覆蓋的方法中使用)。
看下面的例子。
import types
class Dog:
def bark(self):
print "WOOF"
boby = Dog()
boby.bark() # WOOF
def _bark(self):
print "WoOoOoF!!"
boby.bark = types.MethodType(_bark, boby)
boby.bark() # WoOoOoF!!
我發現這是最準確的答案,原來的問題
https://stackoverflow.com/a/10829381/7640677
import a
def _new_print_message(message):
print "NEW:", message
a.print_message = _new_print_message
import b
b.execute()
爲了解釋@ codelogic的出色答卷,我提出了一個更明確的辦法。這與.
運算符在將其作爲實例屬性訪問時徹底綁定類方法的方法相同,只不過您的方法實際上是在類之外定義的函數。
使用@ codelogic的代碼,唯一的區別是該方法是如何綁定的。我在Python中使用的函數和方法是非數據descriptors,並且調用了__get__
方法。請特別注意,原始文件和替換文件都具有相同的簽名,這意味着您可以將替代文件編寫爲完整的類方法,通過self
訪問所有實例屬性。
class Dog: def bark(self): print "Woof" def new_bark(self): print "Woof Woof" foo = Dog() # "Woof" foo.bark() # replace bark with new_bark for this object only foo.bark = new_bark.__get__(foo, Dog) foo.bark() # "Woof Woof"
通過將綁定方法分配給實例屬性,您已經創建了覆蓋方法的幾乎完整的模擬。缺少的一個便利功能是訪問super
的無參數版本,因爲您不在類定義中。另一件事是你的綁定方法的__name__
屬性不會像它在類定義中那樣取得它重寫的函數的名字,但你仍然可以手動設置它。第三個區別是你的手動綁定方法是一個純屬性引用,它恰好是一個函數。 .
運算符只會獲取該引用。另一方面,當從實例調用常規方法時,綁定過程每次都會創建一個新的綁定方法。
順便說一句,這個工作的唯一原因是實例屬性覆蓋非數據描述符。數據描述符有__set__
方法,哪些方法(幸運的是你)沒有。類中的數據描述符實際上優先於任何實例屬性。這就是爲什麼你可以分配給一個屬性:當你嘗試進行分配時,它們的__set__
方法會被調用。我個人喜歡更進一步,在實例的__dict__
中隱藏底層屬性的實際值,正常情況下,該屬性無法訪問,因爲該屬性會遮蓋它。
您還應該記住這對於magic (double underscore) methods毫無意義。魔術方法當然可以用這種方式重寫,但是使用它們的操作只能看類型。例如,您可以將__contains__
設置爲您的實例中的特殊內容,但撥打x in instance
將忽略該內容,並使用type(instance).__contains__(instance, x)
來代替。這適用於Python data model中指定的所有魔術方法。
一個小小的評論,當你做funcType(new_bark,foo,Dog)它的名字==樹皮和實例方法Dog.new_bark在foo .__ dict__中加入嗎?因此,當您再次調用它時,首先查找實例字典並請求它, – 2013-11-29 02:23:18
請解釋它的作用,特別是`funcType`的作用以及爲什麼它是必需的。 – 2016-07-13 04:30:17
我認爲這可以通過使用`funcType = types.MethodType`(在導入`types`後)而不是`funcType = type(Dog.bark)`來使得更簡單和更明確。 – 2016-11-05 23:28:45