簡體   English   中英

如何擴展Class實例

[英]How to extend Class instance

MyClassmodule.py定義。 我們無法修改它。 但我們知道Class定義如下所示:

class MyClass:
    def method(self, msg):
        print 'from method:', msg

我通過導入模塊然后聲明一個對象的實例來啟動我的腳本:

import module    
foo = module.MyClass()

然后我寫自己的功能:

def function(msg):
    print 'from function:', msg

現在,每次使用foo.method('')我都想調用function()所以它也打印相同的消息。

這種情況會被稱為monkey patching嗎? 如何實現所需?

是的,它被稱為猴子修補。

這基本上是裝飾,但是在已經定義了類之后手動完成。

from functools import wraps

def wrapper(f):
    @wraps(f)
    def wrapped(*args, **kwargs):
        myFunction()
        return f(*args, **kwargs)
    return wrapped

MyClass.printThis = wrapper(MyClass.printThis)

它將影響MyClass所有實例,甚至是那些在應用補丁之前創建的實例。

如果您不需要動態修改運行時行為,請避免使用猴子修補,並且更喜歡使用繼承來自定義行為,如注釋中所示。 它不那么黑客。

你也可以將它子類化:

class MyClass:
    def method(self, msg):
        print 'from method:', msg

def function(msg):
    print 'from function:', msg

class MyNewClass(MyClass):
    def method(self, msg):
        function(msg)
        MyClass.method(self, msg)

並使用它像:

>>> a = MyNewClass()
>>> a.method("test")
from function: test
from method: test

或者,如果你想讓你的類成為一個“新風格”類(對於Python 2 - 通過你的print語句判斷) - 只需讓MyClass繼承自object ,然后你就可以使用super

class MyClass(object):  # object added here
    def method(self, msg):
        print 'from method:', msg

def function(msg):
    print 'from function:', msg

class MyNewClass(MyClass):
    def method(self, msg):
        function(msg)
        super(self.__class__, self).method(msg)  # super added here

這是wim的答案的替代方案,也涉及猴子修補。 但是,它通過unittest.mock提供的功能來實現。 這種方法的優點是上下文管理器用於在有限的范圍內自動應用和刪除補丁:

from unittest import mock

# This class would be defined in some third-party library
class MyClass:
    def method(self, msg):
        print('from method:', msg)


def function(msg):
    print('from function:', msg)


old_method = MyClass.method


def new_method(self, msg):
    old_method(self, msg)
    function(msg)


# The patch is only applied within this scope
with mock.patch.object(MyClass, 'method', new_method):
    foo = MyClass()
    foo.method('message with patched')

# By this point MyClass is "back to normal"
print('---')
foo.method('message with original')

產量

from method: message with patched
from function: message with patched
---
from method: message with original

結束這個解決方案,直到有更好的發布...

class MyClass:
    def method(self, msg):
        print 'from method:', msg

def function(msg, callback):
    print 'from function:', msg
    callback(msg)

foo = MyClass()
foo.function = function
foo.function(msg='message', callback=foo.method)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM