如何增强 Python 对象的方法?

发布于 2024-10-03 21:06:39 字数 820 浏览 1 评论 0原文

我有一个 Spam 对象列表:

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!

要么

this spam has been poisoned!
this spam is lite!
updating spam!

取决于它是垃圾邮件还是垃圾邮件。

但这不起作用,因为 spam.update() 不会自动传递 self 参数,并且因为如果 tmp 离开范围或发生更改,那么它不会调用旧的更新。我有办法做到这一点吗?

I have a list of Spam objects:

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

some of them might be SpamLite objects:

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

I would like to be able to take an arbitrary object from the list, and add something to it's update method, something like:

def poison(spam):
    tmp = spam.update 
    def newUpdate(self):
        print 'this spam has been poisoned!'
        tmp(self)
    spam.update = newUpdate

I want spam.update() to now either print:

this spam has been poisoned!
updating spam!

or

this spam has been poisoned!
this spam is lite!
updating spam!

depending on whether it was a SpamLite or just a Spam.

But that doesn't work, because spam.update() won't pass in the self argument automatically, and because if tmp leaves scope or changes then it won't call the old update. Is there a way I can do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

深居我梦 2024-10-10 21:06:39
def poison(spam):
    tmp = spam.update
    def newUpdate():
        print 'this spam has been poisoned!'
        tmp()
    spam.update = newUpdate

完整脚本:

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):
    tmp = spam.update # it is a bound method that doesn't take any arguments
    def newUpdate():
        print 'this spam has been poisoned!'
        tmp()
    spam.update = newUpdate


from operator import methodcaller    
L = [Spam(), SpamLite()]
map(methodcaller('update'), L)
map(poison, L)
print "*"*79
map(methodcaller('update'), L)

输出:

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!
def poison(spam):
    tmp = spam.update
    def newUpdate():
        print 'this spam has been poisoned!'
        tmp()
    spam.update = newUpdate

Full Script:

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):
    tmp = spam.update # it is a bound method that doesn't take any arguments
    def newUpdate():
        print 'this spam has been poisoned!'
        tmp()
    spam.update = newUpdate


from operator import methodcaller    
L = [Spam(), SpamLite()]
map(methodcaller('update'), L)
map(poison, L)
print "*"*79
map(methodcaller('update'), L)

Output:

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!
捂风挽笑 2024-10-10 21:06:39

另一种方法,使用 MethodType

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()

Another approach, with MethodType:

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()
感性不性感 2024-10-10 21:06:39

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

您确实应该使用 Mixin 方法并使用多重继承。

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

MonkeyPatching is frowned upon, in the python world.

You should really use the Mixin approach and use Multiple inheritance.

You can then dynamically replace (update) the parents to achieve the desired effect.

林空鹿饮溪 2024-10-10 21:06:39

使用这样的装饰器:

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!

如果您想了解有关装饰器的更多信息,请阅读以下内容: http:// www.drdobbs.com/web-development/184406073

以上并不是一个“好公民”装饰器,阅读文章就知道如何写一个。请务必检查装饰器库: http://pypi.python.org/pypi/decorator

华泰

Use decorators like this:

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()

This prints:

updating spam!
this spam has been poisoned!
updating spam!

If you want to know more about decorators read this: http://www.drdobbs.com/web-development/184406073

The above is not a "good citizen" decorator, read the article to know how to write one. Be sure to check also decorator library: http://pypi.python.org/pypi/decorator

HTH

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文