获取Python 3中的超类的类型

获取Python 3中的超类的类型,python,inheritance,super,superclass,Python,Inheritance,Super,Superclass,我有一个基类,它有两个派生自它的类。我希望基类的方法的行为有所不同,这取决于参数是否与派生类属于同一类型,或者只是基类的实例,而不是不同的类型。这是当前的实施方式: class MyBase: def __init__(self, foo: int): self.foo = foo def __eq__(self, other): return self.foo == other.foo class MyDerived_1(MyBase)

我有一个基类,它有两个派生自它的类。我希望基类的方法的行为有所不同,这取决于参数是否与派生类属于同一类型,或者只是基类的实例,而不是不同的类型。这是当前的实施方式:

class MyBase:
    def __init__(self, foo: int):
        self.foo = foo 

    def __eq__(self, other):
        return self.foo == other.foo 


class MyDerived_1(MyBase):
    def __init__(self, foo: int, bar: int):
        super().__init__(foo)
        self.bar = bar


class MyDerived_2(MyBase):
    def __init__(self, foo: int, bar: int):
        super().__init__(foo)
        self.bar = bar 

    def __eq__(self, other):
        if type(other) == type(self):
            return self.bar == other.bar 
        elif isinstance(other, MyBase):
            return super().__eq__(other)
        else:
            return False
在最后第四行中,我必须显式地引用MyBase。也许这很好,但我的理解是,“super”关键字的一个要点是,它应该允许您更改基类,而无需在类中重新编写任何内容。因此,也就是说,此解决方案的一个潜在问题是,如果MyBase发生更改,则init将正常,因为它调用“super”,但eq不会更新其行为

因此,我尝试用“type(super)”或“type(super())”替换“MyBase”,但它们不引用超类,而是引用对象“super”的类

请注意,这些问题不同于:

等等

因为一旦对象被初始化,他们就会寻找父类

我想我应该可以通过运行MRO找到超级类。但这似乎是一个糟糕的解决方案,因为我不是在寻找整个继承树,我只是想知道超类的类型


有没有一种方法可以从“super”中提取该信息?

首先,当遇到不支持的类型时,您希望从
\uuuuuueq\uuuu
返回
NotImplemented
,这样Python也可以给第二个操作数一个参与相等测试的机会。从:

如果数值方法和富比较方法未对提供的操作数执行操作,则它们应返回此值。(然后,解释器将根据操作员的不同,尝试反射操作或其他回退。)

您的代码实际上应该委托给
super()。\uuuu eq\uuuu()
other
不是同一类型的实例时,不需要在这里测试基类型;基类应该已经负责测试正确的类型或协议

接下来,您可以使用访问定义了方法的类;每当您在嵌套在类定义中的函数定义中使用
super()
\uuuuuu类
时,Python都会添加此闭包:

class MyBase:
    # ...

    def __eq__(self, other):
        if not isinstance(other, __class__):
            # we can't handle the other type, inform Python
            return NotImplemented
        return self.foo == other.foo 

class MyDerived_2(MyBase):
    # ...

    def __eq__(self, other):
        if isinstance(other, __class__):
            # if other is an instance of MyDerived_2, only test for 'bar'
            return self.bar == other.bar 
        # otherwise fall back to the base behaviour
        return super().__eq__(other)
请注意,我使用了
isinstance()
而不是
type()
测试,您希望
MyDerived_2
的子类继承此行为

您也可以依赖duck类型,而不是测试特定的类层次结构;如果另一个对象具有正确的属性名称,则只需假设它可以用于比较:

class MyBase:
    # ...

    def __eq__(self, other):
        try:
            self.foo == other.foo
        except AttributeError:
            # we can't handle the other type, inform Python
            return NotImplemented

class MyDerived_2(MyBase):
    # ...

    def __eq__(self, other):
        try:
            self.bar == other.bar
        except AttributeError:
            # otherwise fall back to the base behaviour
            return super().__eq__(other)

首先,当遇到不支持的类型时,您希望从
\uuuuu eq\uuuu
返回
NotImplemented
,这样Python也可以让第二个操作数有机会参与相等性测试。从:

如果数值方法和富比较方法未对提供的操作数执行操作,则它们应返回此值。(然后,解释器将根据操作员的不同,尝试反射操作或其他回退。)

您的代码实际上应该委托给
super()。\uuuu eq\uuuu()
other
不是同一类型的实例时,不需要在这里测试基类型;基类应该已经负责测试正确的类型或协议

接下来,您可以使用访问定义了方法的类;每当您在嵌套在类定义中的函数定义中使用
super()
\uuuuuu类
时,Python都会添加此闭包:

class MyBase:
    # ...

    def __eq__(self, other):
        if not isinstance(other, __class__):
            # we can't handle the other type, inform Python
            return NotImplemented
        return self.foo == other.foo 

class MyDerived_2(MyBase):
    # ...

    def __eq__(self, other):
        if isinstance(other, __class__):
            # if other is an instance of MyDerived_2, only test for 'bar'
            return self.bar == other.bar 
        # otherwise fall back to the base behaviour
        return super().__eq__(other)
请注意,我使用了
isinstance()
而不是
type()
测试,您希望
MyDerived_2
的子类继承此行为

您也可以依赖duck类型,而不是测试特定的类层次结构;如果另一个对象具有正确的属性名称,则只需假设它可以用于比较:

class MyBase:
    # ...

    def __eq__(self, other):
        try:
            self.foo == other.foo
        except AttributeError:
            # we can't handle the other type, inform Python
            return NotImplemented

class MyDerived_2(MyBase):
    # ...

    def __eq__(self, other):
        try:
            self.bar == other.bar
        except AttributeError:
            # otherwise fall back to the base behaviour
            return super().__eq__(other)

我想您可能需要使用
inspect
模块,它是
getclasstree()
函数:

这将产生:

[(<class '__main__.MyBase'>, (<class 'object'>,)), [(<class '__main__.MyDerived_2'>, (<class '__main__.MyBase'>,))]]
[(,(,),[(,(,))]]

我认为您可能需要使用
inspect
模块,它是
getclasstree()
函数:

这将产生:

[(<class '__main__.MyBase'>, (<class 'object'>,)), [(<class '__main__.MyDerived_2'>, (<class '__main__.MyBase'>,))]]
[(,(,),[(,(,))]]

显然不相关,但为了正确的子类型,
MyDerived\u2.\uuuuu eq\uuuu
应始终调用
super()。\uuuuu eq\uuuuu
-对
self.bar
的测试应是对
super()。\uuuu eq\uuu
的补充,而不是替代(当然,只有当
MyDerived2
被认为是
MyBase
的一个适当的子类型时,这才有意义。)显然不相关,但对于适当的子类型,
MyDerived2.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuu2.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu应始终调用
super()。