python按类名切换?

时间:2010-02-28 15:36:12

标签: python syntax switch-statement

我目前正在这样做,根据对象的类型做不同的事情:

    actions = {
        SomeClass: lambda: obj.name
        AnotherClass: lambda: self.normalize(obj.identifier)
        ...[5 more of these]...
    }

    for a in actions.keys():
        if isinstance(obj, a):
            return actions[a]()

是否可以删除for循环,并执行类似的操作?

actions[something to do with obj]()

6 个答案:

答案 0 :(得分:6)

class SomeClass( object ):
....
    def action( self ):
        return self.name

class AnotherClass( object ):
....
    def action( self ):
        return self.normalize( self.identifier )

[5 more classes like the above two]

a.action()

简单。清晰。更具扩展性。减少魔法。没有字典。没有循环。

答案 1 :(得分:1)

actions[obj.__class__]()
如果obj实际上是({)SomeClass的实例而不是子类的实例,则

有效 - 所以如果可能是这种情况,结果将与您当前处理它的方式不同。另请注意,如果类没有相应的操作,则可能会引发KeyError。要像现在一样处理这种情况(即什么也不做),你可以使用

actions.get(obj.__class__, lambda: None)

返回默认值。

哦,听听S.Lott对你问题的评论。在许多情况下,有更好的方法来实现这样的事情。例如,您可以让所有课程定义do_whatever(self),然后致电obj.do_whatever()

答案 2 :(得分:1)

我假设你有所有这些的父类,或者至少是一个mixin。在父或mixin中放置一个默认的返回函数,然后在那些不同的函数中覆盖它...这是唯一正确的方法。

当然,它会产生额外的代码,但至少它是封装的,可扩展的。假设您想为另外五个课程添加支持。不要在那里改变代码,只需将正确的代码添加到新类中。从它的外观来看,它是每个类两行(函数定义和返回行)。那不错,是吗?

如果obj不是包含返回函数的类,则会引发异常,您可以通过干净的良心捕获并忽略该异常。

class MyMixin:
  def my_return(self, *args):
    return self.name
  ... possibly other things...

class SomeClass(MyMixin):
  ... no alteration to the default ...

class AnotherClass(MyParent, MyMixin):
  def my_return(self, *args):
    return args[0].normalize(self.identifier)
  ... blabla


# now, this is in the caller object...
try:
  rval = obj.my_return(self) # this is the caller object 'self', not the 'self' in the 'obj'
  #dosomething with rval
except Exception:
  pass #no rval for this object type, skipping it...

答案 3 :(得分:0)

怎么样?
actions[obj.__class__]()

答案 4 :(得分:0)

actions[type(obj)]()

答案 5 :(得分:0)

results = [func() for cls, func in actions.iteritems() if isinstance(obj, cls)]

如果您的对象isinstance为零或更多类密钥,则会有零个或多个结果。

使用type(obj)作为键只有在您的对象属于该类型时才有效。如果继续在继承树下面,你会错过它。