找到与现有类型最接近的匹配类型的最佳方法是什么?

时间:2009-03-06 21:37:18

标签: python types

我在Python 2.5中有一个类和类型的注册表,如下所示:

class ClassA(object):
    pass

class ClassB(ClassA):
    pass 

MY_TYPES = {
    basestring : 'A string',
    int : 'An integer',
    ClassA : 'This is ClassA or a subclass',
}

我希望能够将类型传递给函数,并让它在层次结构中查找最接近的匹配类型。因此,查找str将返回"A string"并查找ClassB将返回"This is ClassA or a subclass"问题是,我不知道如何找到超类(或者更确切地说,跟踪类型对象的MRO链。

处理此问题的最佳方式是什么?

4 个答案:

答案 0 :(得分:4)

from inspect import getmro
[st for cls, st in MY_TYPES.items() if cls in getmro(ClassB)]

['This is ClassA or a subclass']

或者如果您只对第一个匹配生成器版本感兴趣:

(st for cls, st in MY_TYPES.iteritems() if cls in getmro(ClassB))

答案 1 :(得分:2)

要获取课程的超类,请使用__bases__

class ClassA(object):
    pass

class ClassB(ClassA):
    pass

print ClassB.__bases__
(<class '__main__.ClassA'>,)

谨防int之类的事情。所有这些的基础将是<type 'object'>。您必须进行一些测试和迭代才能匹配您在示例中列出的dict键。

另一种选择是在任何对象实例上使用isinstance,或在参数上使用issubclass,对每个对象键进行测试。有些人认为isinstance及其同类是魔鬼的标志,但是你可以看到。但是,请注意使用带有整数和其他此类类型的issubclass。你可能需要结合使用dict键的几种方法。

答案 2 :(得分:1)

  

(st为cls,st为MY_TYPES.iteritems(),如果是getmro(ClassB)中的cls)

更简单的写作方式是:

(st for cls, st in MY_TYPES.iteritems() if issubclass(ClassB, cls))

然而,这并没有找到“最近”的匹配;如果“对象”在查找中,它可以匹配所有内容!如果您在查找中有其他东西的子类,或者您想支持多重继承,那么您必须选择MRO中第一个的那个:

for cls in inspect.getmro(ClassB):
    if cls in MY_TYPES:
        print MY_TYPES[cls]
        break
else:
    print 'Dunno what it is'

无论如何......我通常认为类型查找只是一点代码味道,没有更好的方法可以做你想要的吗?

答案 3 :(得分:0)

这实际上是通用功能的工作。请参阅PEAK-RulesPEP 3124。通用函数允许您根据参数类型或甚至更复杂的表达式调度任意函数。

或者,如果你真的是一个惩罚的傻瓜,请见chapterPractical Common Lisp {/ 3}}。