覆盖没有继承的类方法(python)

时间:2011-07-04 19:12:48

标签: python

首先,如果你们认为我尝试做事的方式不是Pythonic,请随意提供其他建议。

我有一个对象,其功能需要根据外部事件进行更改。我最初做的是创建一个继承自原始对象的新对象(让我们称之为OrigObject())并覆盖更改的方法(让我们调用新对象NewObject())。然后我修改了两个构造函数,以便它们可以接受另一个类型的完整对象,以根据传入的对象填充自己的值。然后,当我需要更改功能时,我只需执行myObject = NewObject(myObject)

我现在开始看到这种方法有几个问题。首先,需要更新引用该对象的其他位置以引用新类型(例如,上述语句只会更新本地myObject变量)。但是这并不难更新,只有烦人的部分才会记住每次更改对象时在其他地方更新它以防止奇怪的程序行为。

其次,我注意到需要NewObject()中的单个方法的场景,以及来自OrigObject()的其他方法,我需要能够动态切换功能。它似乎不再是使用继承的最佳解决方案,我需要在M * N中创建不同的类(其中M是类可以改变的方法数,N是变化的数量)每个方法)都继承自OrigObject()

我正在考虑使用属性重新映射,但我似乎遇到了问题。例如,假设我有这样的事情:

def hybrid_type2(someobj, a):
    #do something else
    ...

class OrigObject(object):
    ...
    def hybrid_fun(self, a):
        #do something
        ...

    def switch(type):
        if type == 1:
            self.hybrid_fun = OrigObject.hybrid_fun
        else:
            self.fybrid_fun = hybrid_type2

问题是,在执行此操作并尝试在切换后调用新的hybrid_fun之后,我得到一个错误,指出hybrid_type2()只接受2个参数,但我传递了一个。该对象似乎不再将自身作为新函数的参数传递,就像它使用自己的方法一样,我可以采取哪些措施来解决这个问题?

我尝试在类中包含hybrid_type2然后使用self.hybrid_fun = self.hybrid_type2工作,但是使用self.hybrid_fun = OrigObject.hybrid_fun会导致类似的错误(抱怨第一个参数应该是OrigObject类型)。我知道我可以在OrigObject.hybrid_fun()中定义OrigObject.hybrid_type1()逻辑,所以我可以将其恢复为与我设置它相同的方式(相对于实例,而不是相对于类,以避免对象不是第一个论点)。但是我想在这里询问是否有更清洁的方法,我没有在这里看到?感谢

编辑: 谢谢大家,我已经为几个效果很好的解决方案提供了积分。我基本上最终使用了一个使用types.MethodType()的策略模式,我接受了解释如何在python中执行策略模式的答案(维基百科文章更通用,Python中不需要使用接口)

5 个答案:

答案 0 :(得分:5)

您需要Strategy Pattern

答案 1 :(得分:3)

使用types模块为特定实例创建实例方法。

例如

import types

def strategyA(possible_self):
    pass

instance = OrigObject()

instance.strategy = types.MethodType(strategyA, instance)

instance.strategy()

请注意,这仅影响此特定实例,不会影响其他实例。

答案 2 :(得分:2)

在Python中阅读descriptors。下一个代码应该有效:

else:
    self.fybrid_fun = hybrid_type2.__get__(self, OrigObject)

答案 3 :(得分:1)

如此定义它如何:

def hybrid_type2(someobj, a):
    #do something else
    ...

def hybrid_type1(someobj, a):
    #do something
    ...

class OrigObject(object):

    def __init__(self):
        ...
        self.run_the_fun = hybrid_type1

    ...
    def hybrid_fun(self, a):
        self.run_the_fun(self, a)

    def type_switch(self, type):
        if type == 1:
            self.run_the_fun = hybrid_type1
        else:
            self.run_the_fun = hybrid_type2

答案 4 :(得分:0)

您可以在运行时更改类:

class OrigObject(object):
    ...
    def hybrid_fun(self, a):
        #do something
        ...
    def switch(self):
        self.__class__ = DerivedObject


class DerivedObject(OrigObject):
    def hybrid_fun(self, a):
        #do the other thing
        ...
    def switch(self):
        self.__class__ = OrigObject