How to determine the closest common ancestor class

纵饮孤独 提交于 2019-12-12 20:23:13

问题


Suppose I have four classes: A, B derived from A, C derived from A, and D derived from C. (So I always have single inheritance.) In python, what is the best way to determine the closest common ancestor of any two (instances of such) classes? Specifically, I need a function clcoancl(X,Y) for which clcoancl(A, B) == A, clcoancl(B, C) == A, and clcoancl(C, D) == C.


回答1:


This should work for single or multiple inheritance, with any number of classes as input:

import inspect
from collections import defaultdict

def clcoancl(*cls_list):
    mros = [list(inspect.getmro(cls)) for cls in cls_list]
    track = defaultdict(int)
    while mros:
        for mro in mros:
            cur = mro.pop(0)
            track[cur] += 1
            if track[cur] == len(cls_list):
                return cur
            if len(mro) == 0:
                mros.remove(mro)
    return None # or raise, if that's more appropriate

As both NPE and Daniel Rossman have mentioned though, this is probably not the optimal solution to your root problem.




回答2:


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

# get the list of ancestors (assuming single inheritance!)
def ancl(cls):
    ret = []
    while cls is not object:
        ret.append(cls)
        cls = cls.__bases__[0]
    ret.append(object)
    return ret

def clcoancl(cls1, cls2):
    ancl1 = ancl(cls1)
    ancl2 = ancl(cls2)
    # find the first class present in both ancl1 and ancl2
    while len(ancl1) > 0 and len(ancl2) > 0 and ancl1[-1] == ancl2[-1]:
        ret = ancl1.pop(-1)
        ancl2.pop(-1)
    return ret

print clcoancl(A, B)
print clcoancl(B, C)
print clcoancl(C, D)

Whether you actually need this is a different matter, as pointed out by @DanielRoseman is his comment to your question.



来源:https://stackoverflow.com/questions/15788725/how-to-determine-the-closest-common-ancestor-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!