2011-07-04 124 views
2

首先,如果你们认为我尝试做事情的方式不是Pythonic,请随时提供其他建议。覆盖没有继承的类方法(python)

我有一个对象,其功能需要根据外部事件进行更改。我最初做的是创建一个从原始继承的新对象(我们称它为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_type1()里面定义OrigObject.hybrid_fun()逻辑,所以我可以按照我设置它的相同方式(相对于实例,而不是相对于类来避免使对象不是第一个参数)恢复它。但我想问这里是否有更清晰的方法,我没有在这里看到?谢谢

编辑: 感谢球员们,我已经给出了几个解决方案运行良好的积分。我基本上最终使用了使用types.MethodType()的策略模式,我已经接受了解释如何在python中实现策略模式的答案(维基百科的文章更通用一些,并且Python中不需要使用接口) 。

+0

用于创意方法的+1 – Predator

+0

您需要在类级别上指定该方法,然后它将自己作为参数传递。 (如果已经有一个同名的对象级别的方法,则不会工作)另外:您可以扩展“需要根据外部事件更改功能”。 ?我们可能能够提供更好的方法;) – phant0m

回答

3

使用类型的模块来创建特定实例的实例方法。

例如。

import types 

def strategyA(possible_self): 
    pass 

instance = OrigObject() 

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

instance.strategy() 

请注意,这只影响这个特定的实例,不会影响其他实例。

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 
+0

这不起作用,因为该方法没有绑定。你需要将这些方法赋值给'OrigObject.run_the_fun',但这会改变这个类的所有实例的行为。 – phant0m

+0

@ phant0m似乎工作[这里](http://ideone.com/X9nMK)。我并没有完全意识到为什么它在绑定/非绑定方法方面起作用的微妙之处。我认为发生的事情是,self.run_the_fun被视为恰好是一个函数的变量。 – trutheality

+0

啊,我没有注意到你有一个额外的方法来运行它。我以为你想在它调用时工作:'orig_object.run_the_fun(“something”)' – phant0m

2

在Python阅读descriptors。下面的代码应该工作:

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

这是如何使它成为描述符? – phant0m

+0

@ phant0m nope。这使它成为'unbound method' –

+0

啊,我以为你想让他使用描述符。我明白你的意思了。你会想让它成为一个绑定的方法,即通过自己而不是无 – phant0m

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