Python 如何知道哪个基类将特定属性添加到子类对象

Python 如何知道哪个基类将特定属性添加到子类对象,python,python-3.x,multiple-inheritance,Python,Python 3.x,Multiple Inheritance,我正在从事一个项目,其中包含来自不同文件中多个模块的长层次类 我想知道继承链中的类C何时获得属性A (然后我可以得到定义了C的模块M并检查代码) 考虑下面的代码示例,假设除了2子类之外的所有类都在其他模块中,是否有类似于:attribute\u base(o4,'a')的命令,输出:Base1 class SweetDir: def __sweet_dir__(self): """ Same as dir, but will omit special at

我正在从事一个项目,其中包含来自不同文件中多个模块的长层次类

我想知道继承链中的类C何时获得属性A (然后我可以得到定义了C的模块M并检查代码)

考虑下面的代码示例,假设除了
2
子类之外的所有类都在其他模块中,是否有类似于:
attribute\u base(o4,'a')
的命令,输出:
Base1

class SweetDir:
    def __sweet_dir__(self):
        """
        Same as dir, but will omit special attributes
        :return: string
        """
        full_dir = self.__dir__()
        sweet_dir  = []
        for attribute_name in full_dir:

            if not (    attribute_name.startswith('__')
                    and  attribute_name.endswith('__')):
                #not a special attribute
                sweet_dir.append(attribute_name)
        return sweet_dir

class Base1(SweetDir):
    def __init__(self):
        super(Base1,self).__init__()
        self.a = 'a'

class Base2(SweetDir):
    def __init__(self):
        super(Base2,self).__init__()
        self.b = 'b'

class ChildOf1 (Base1):
    def __init__(self):
        super(ChildOf1,self).__init__()
        self.c = 'c'

class GrandChildOf1ChildOf2 (Base2,ChildOf1):
    def __init__(self):
        super(GrandChildOf1ChildOf2,self).__init__()
        self.d = 'd'   


o1 = Base1()
o2 = Base2()
o3 = ChildOf1()
o4 = GrandChildOf1ChildOf2()
print(o1.__sweet_dir__())
print(o2.__sweet_dir__())
print(o3.__sweet_dir__())
print(o4.__sweet_dir__())
输出:

['a']
['b']
['a', 'c']
['a', 'b', 'c', 'd']

我不认为有一个内置的功能,但类似的东西将工作(它需要改进):

这将返回类的第一个基类,该基类获得了您要查找的属性。这显然不是完美的。如果两个或多个基类具有相同的属性(具有相同的名称),则它可能不会返回获取该属性的实际类,但在示例中它会起作用。 [使用AKX注释更新:使用
\uuuu mro\uuu
实际上应该解决这个问题]

[更新:有一种方法可以在没有实例的情况下完成此操作,遵循这一有大量文档记录的答案:]


getmembers
提供类的每个成员,包括我们想要的init方法。我们需要检查它是否真的是一个函数
(hasattr(成员[1],“\uuuuu code\uuuuuuuu”)
,因为如果没有为类定义
\uuuuu init\uuuuuuuuuuuu
函数(如示例中的SweetDir),这将返回一个包装描述符。我们在罕见(可能?)的情况下循环成员。有几种
\uuuuu init\uuuu
方法。

如果使用Python3,
\uuuuuu mro\uuuu
更好。“此属性是在方法解析期间查找基类时考虑的类的元组。”没错,我不知道这一点,谢谢!唯一的问题是,您的\u类。\uuuu mro\uuuu包含“您的\u类”,但它很容易修复。使用
tmp\u inst=base\u class()
可以通过调用无参数的构造函数来创建临时对象。这并不总是有效的,因为某些基函数的
\uuuu init\uuu
函数可能需要参数。还有别的办法吗?我想不会,因为类成员是在
\uuuuu init\uuuuu
中添加的。实际上有(但有点脏),感谢
\uuuu init\uuuuu
函数的提示!
def attribute_base(your_class, your_attr):

    for base_class in your_class.__mro__:
        if base_class != your_class:
            tmp_inst = base_class()
            if hasattr(tmp_inst, your_attr):
                return base_class
from inspect import getmembers

def attribute_base(your_class, your_attr):
    for base_class in your_class.__mro__:
        if base_class != your_class:
            members = [member[1].__code__.co_names for member in getmembers(base_class) if '__init__' in member and hasattr(member[1], "__code__")]
            for member in members:
                if your_attr in members:
                    return base_class