【问题标题】:How can I sort a list of Python classes by inheritance depth?如何按继承深度对 Python 类列表进行排序?
【发布时间】:2014-05-14 16:40:07
【问题描述】:

如何在 Python 中对类列表进行排序,确保任何子类在列表中的任何父类之前?

我问是因为我想从类型列表中查看一个对象属于什么类型,但如果它属于多个,则找到最具体的类型。

【问题讨论】:

  • 在排序键函数中使用issubclass
  • (通常:sorted(classes, cmp=lambda x, y: 1 if issubclass(x, y) else -1)
  • @njzk2:那个比较器不一致;没有继承关系的类相互比较小于另一个,一个类总是比较大于自己。
  • 这只是我脑海中的一个例子,不是一个实际的答案。

标签: python class oop method-resolution-order


【解决方案1】:

只需按len(cls.mro())排序。

如果C2C1 的子类,它必须持有len(C1.mro()) < len(C2.mro())(因为C1.mro() 中的每个类也必须出现在C2.mro() 中)。因此,您可以简单地按mro list的长度排序:

class A(object): pass
class X(object): pass
class B(A, X): pass
class C(B): pass
class D(C): pass

sorted([B, C, A, D, X], key = lambda cls: len(cls.mro()))
=> [__main__.A, __main__.X, __main__.B, __main__.C, __main__.D]

为了也支持旧式类,您可以将cls.mro() 替换为inspect.getmro(cls)

【讨论】:

    【解决方案2】:

    更好的方法是使用一个集合,然后沿着目标类的继承树移动。

    def find_parent(target, class_set):
        if target in class_set:
            return [target]
        else:
            bases = []
            for parent in target.__bases__:
                result = find_parent(parent, class_set)
                if result is not None:
                    bases.extend(result)
            return bases
    

    例子:

    class A(object):
        pass
    
    class B(str):
        pass
    
    class C(A):
        pass
    
    class D(A, dict):
        pass
    
    class_set = {dict, A}
    
    print find_parent(A, class_set)
    print find_parent(B, class_set)
    print find_parent(C, class_set)
    print find_parent(D, class_set)
    

    给你这个结果:

    [<class '__main__.A'>]
    []
    [<class '__main__.A'>]
    [<class '__main__.A'>, <type 'dict'>]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-21
      • 1970-01-01
      • 2020-05-07
      相关资源
      最近更新 更多