有没有办法在Python中覆盖实例级别的类方法?例如:
class Dog:
def bark(self):
print "WOOF"
boby = Dog()
boby.bark() # WOOF
# METHOD OVERRIDE
boby.bark() # WoOoOoF!!
Run Code Online (Sandbox Code Playgroud)
cod*_*gic 149
是的,这是可能的:
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"
Run Code Online (Sandbox Code Playgroud)
Har*_*mal 31
您需要在类型模块中使用MethodType.MethodType的目的是覆盖实例级方法(以便在覆盖方法中可以使用self).
见下面的例子.
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!!
Run Code Online (Sandbox Code Playgroud)
nos*_*klo 25
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!!
Run Code Online (Sandbox Code Playgroud)
boby如果需要,可以在函数内部使用变量.由于您仅为此一个实例对象覆盖该方法,因此这种方式更简单,并且与使用具有完全相同的效果self.
Mad*_*ist 21
为了解释@ codelogic的优秀答案,我提出了一种更明确的方法.这是一种技术,.当您将类方法作为实例属性访问时,操作员会彻底绑定类方法,除了您的方法实际上是在类之外定义的函数.
使用@ codelogic的代码,唯一的区别在于方法的绑定方式.我使用的事实是函数和方法是Python 中的非数据描述符,并调用该__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"
通过将绑定方法分配给实例属性,您已创建了几乎完全覆盖方法的模拟.缺少一个方便的功能是访问no-arg版本super,因为您不在类定义中.另一件事是__name__绑定方法的属性不会像它在类定义中那样采用它覆盖的函数的名称,但您仍然可以手动设置它.第三个区别是你的手动绑定方法是一个普通的属性引用,恰好是一个函数.该.运营商不只是获取该引用.另一方面,当从实例调用常规方法时,绑定过程每次都会创建一个新的绑定方法.
顺便说一句,这种方法的唯一原因是实例属性覆盖非数据描述符.数据描述符有__set__方法,哪种方法(幸运的是)不这样做.类中的数据描述符实际上优先于任何实例属性.这就是您可以分配给属性的原因:__set__当您尝试进行分配时,会调用它们的方法.我个人喜欢更进一步,隐藏实例中底层属性的实际值,__dict__正常情况下它无法访问,因为属性会影响它.
你还应该记住,这对于魔术(双下划线)方法来说毫无意义.魔术方法当然可以通过这种方式被覆盖,但使用它们的操作只能查看类型.例如,您可以__contains__在实例中设置特殊内容,但调用x in instance会忽略它并使用type(instance).__contains__(instance, x).这适用于Python 数据模型中指定的所有魔术方法.
use*_*245 13
functools.partial由于这里没有人提到:
from functools import partial
class Dog:
name = "aaa"
def bark(self):
print("WOOF")
boby = Dog()
boby.bark() # WOOF
def _bark(self):
print("WoOoOoF!!")
boby.bark = partial(_bark, boby)
boby.bark() # WoOoOoF!!
Run Code Online (Sandbox Code Playgroud)
S.L*_*ott 12
请不要如图所示这样做.当您将实例monkeypatch与该类不同时,您的代码将变得不可读.
你无法调试monkeypatched代码.
当你发现中的错误boby和print type(boby),你会看到(一)它是一只狗,但(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!!
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
51556 次 |
| 最近记录: |