上调用A类的方法取决于类型参数的

问题描述:

class Class1(object): 
    ... 

class Class2(object): 
    ... 

class Class3(object): 
    ... 

class A(object): 
    def _methA(parm1, parm2) 
     ... 

    def _methB(parm1, parm2) 
     ... 

    def _methC(parm1, parm2) 
     ... 

    def manager(parm1, method, params) 
     ... 
     if parm1.__class__.__name__==Class1.__name__: 
      response = _methA(parm1, params) 
     elif parm1.__class__.__name__==Class2.__name__: 
      response = _methB(parm1, params) 
     elif io_source.__class__.__name__==Class3.__name__: 
      response = _methC(parm1, params) 
     else: 
      raise Exception, "Unsupported parm1" 
     ... 

我不喜欢的方式,在manager()if/elif块看着它重构为这样:上调用A类的方法取决于类型参数的

def manager(parm1, method, params) 
    ... 
    try: 
     response = { 
       Class1.__name__: lambda parm1, parms: _methA(parm1, parms), 
       Class2.__name__: lambda parm1, parms: _methB(parm1, parms), 
       Class3.__name__: lambda parm1, parms: _methC(parm1, parms) 
       }[parm1.__class__.__name__](parm1, parms) 
    except KeyError: 
     raise Exception, "Unsupported parm1" 

但事实证明代码仍然在看类名困扰我 - 我真的不知道如何解释为什么... 它应该打扰我吗?

有没有更好的方式来编写代码来调用A类的方法是,根据类的参数之一,触发在不同的方法的调用?

PS。对不起这个人为的例子,但发布实际的代码会让问题变得更加复杂。我想这个问题要提炼其精髓...

+0

+1:这是最小的一段代码的一个很好的例子显示问题。 – 2009-12-18 15:41:09

这是实现多态的许多错误方法之一。你不应该看类名。查看班级名称会让你感到困扰,因为这意味着你没有正确授予责任。

将每个方法移到相应的类中。

class Class1(object): 
    def method(self, theA, params): 
     theA.methA(params) 

class Class2(object): 
    def method(self, theA, params): 
     theA.methB(params) 

class Class3(object): 
    def method(self, theA, params): 
     theA.methC(params) 

class A(object): 
    def methA(parm1, parm2) 
     ... 

    def methB(parm1, parm2) 
     ... 

    def methC(parm1, parm2) 
     ... 

    def manager(parm1, method, params) 
     ... 
     param1.method(self, params) 
+0

+1表达为什么我觉得在查看类名称的代码时感到不安。 :-)是的,这是我们正在讨论的事情之一 - 为什么这些方法没有封装在Class1,Class2和Class3中。在实际的代码中有它的原因(虽然它们可能不是很好的理由)。 – cethegeek 2009-12-18 15:34:39

+2

@celopes:“他们可能不是很好的理由” - 几乎是正确的。他们不是很好的理由。他们“似乎”使“Class1”,“Class2”和“Class3”知道“A”的特征;但是这个判断是错误的。 A的“隐藏”方法真的是* A的公共接口。 – 2009-12-18 15:40:18

我宁愿

if isinstance(parm1, Class1): 
    _methA(parm1, params) 
elif isinstance(parm1, Class2): 
    _methB(parm1, params) 
elif isinstance(parm1, Class3): 
    _methC(parm1, params) 

但仍闻起来有设计缺陷的。 :)

也许你的三类ClassX倒是应该都有一个单一的方法meth(params),那么你的经理可能只是打电话parm1.meth(params)

您正试图模拟哪种语言极客称为“multiple dispatch”或“multimethods”。链接到维基百科的文章有很好的讨论,包括Python示例。

我通常做这种处理消息的时候,所以我没有吨IFS的...但它仍然使用了类名。一个穷人的多态性

类 - 但是,正如美国洛特说,Python支持真正的多态,为什么不使用它:对

class Handler(object): 
    # .. stuff 

    def dispatch(self, msg): 
     handlername = "on_%s" % type(msg) 
     return getattr(self, handlername, 'on_missing_handler')(msg) 

    def on_SomeClass(self, msg): 
     # msg is of SomeClass here .. 

    def on_SomeOtherClass(self, msg): 
     # msg is of SomeOtherClass here .. 

    def on_missing_handler(self, msg): 
     # there is no other handler for msg