如何扩展Python对象的方法?

如何扩展Python对象的方法?,python,methods,Python,Methods,我有一个垃圾邮件对象列表: class Spam: def update(self): print('updating spam!') 其中一些可能是SpamLite对象: class SpamLite(Spam): def update(self): print('this spam is lite!') Spam.update(self) 我希望能够从列表中获取任意对象,并向其更新方法中添加一些内容,例如: def pois

我有一个垃圾邮件对象列表:

class Spam:
    def update(self):
        print('updating spam!')
其中一些可能是SpamLite对象:

class SpamLite(Spam):
    def update(self):
        print('this spam is lite!')
        Spam.update(self)
我希望能够从列表中获取任意对象,并向其更新方法中添加一些内容,例如:

def poison(spam):
    tmp = spam.update 
    def newUpdate(self):
        print 'this spam has been poisoned!'
        tmp(self)
    spam.update = newUpdate
我希望spam.update()现在可以打印:

this spam has been poisoned!
updating spam!

这取决于它是垃圾邮件还是仅仅是垃圾邮件

但这不起作用,因为spam.update()不会自动传入self参数,而且因为如果tmp离开作用域或进行更改,它就不会调用旧的更新。我有办法做到这一点吗

def poison(spam):
    tmp = spam.update
    def newUpdate():
        print 'this spam has been poisoned!'
        tmp()
    spam.update = newUpdate
完整脚本: 输出: 更新垃圾邮件! 这个垃圾邮件是lite! 更新垃圾邮件! ******************************************************************************* 此垃圾邮件已中毒! 更新垃圾邮件! 此垃圾邮件已中毒! 这个垃圾邮件是lite! 更新垃圾邮件! 另一种方法是:


在python世界中,MonkeyPatching是不受欢迎的

您应该真正使用Mixin方法并使用多重继承


然后,您可以动态地替换(更新)父级以达到所需的效果。

使用如下装饰器:

def method_decorator(f):
    def wrapper(self, *args, **kwargs):
        print('this spam has been poisoned!')
        return f(self)
    return wrapper

class Spam:
    def update(self):
        print('updating spam!')

    @method_decorator
    def update2(self):
        print('updating spam!')

Spam().update()
Spam().update2()
这张照片是:

updating spam!
this spam has been poisoned!
updating spam!
如果您想了解更多关于装饰师的信息,请阅读以下内容:

以上不是一个“好公民”的装潢者,读了这篇文章就知道怎么写了。请确保同时检查装饰程序库:


HTH

多态性?应该很容易实现,但我从来没有写过python。顺便说一句,这通俗地说就是“猴子补丁”。使用
super
而不是调用
Spam.update
,这被认为是一种很好的做法。这如何允许一个人在特定实例上而不是其他实例上更改方法?你是说要更改它的
\uuuuuu class\uuuuuu
属性吗?@themissinglint:是的。在这种情况下,
self
被称为
spam
。您不需要显式地传递它;只要在需要时在
newUpdate()
中使用它即可。如果您想更改
Spam
类的所有实例的
update
方法(不仅仅是所选的几个),那么您可以:
Spam.update=types.UnboundMethodType(lambda self:…对self做点什么…,None,Spam)
;看见 updating spam! this spam is lite! updating spam! ******************************************************************************* this spam has been poisoned! updating spam! this spam has been poisoned! this spam is lite! updating spam!
class Spam:
    def update(self):
        print('updating spam!')

class SpamLite(Spam):
    def update(self):
        print('this spam is lite!')
        Spam.update(self)

def poison(spam):
    import types
    tmp = spam.update 
    def newUpdate(self):
        print 'this spam has been poisoned!'
        tmp()
    newUpdate = types.MethodType(newUpdate, spam, Spam)
    spam.update = newUpdate

spam = Spam()
spam_lite = SpamLite()
poison(spam)
poison(spam_lite)
spam.update()
print
spam_lite.update()
def method_decorator(f):
    def wrapper(self, *args, **kwargs):
        print('this spam has been poisoned!')
        return f(self)
    return wrapper

class Spam:
    def update(self):
        print('updating spam!')

    @method_decorator
    def update2(self):
        print('updating spam!')

Spam().update()
Spam().update2()
updating spam!
this spam has been poisoned!
updating spam!