Nei*_*eil 6 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):
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
Run Code Online (Sandbox Code Playgroud)
在倒数第四行中,我必须明确引用 MyBase。也许这很好,但我的理解是“super”关键字的一个要点是它应该允许您更改基类,而不必重新编写类中的任何内容。因此,该解决方案的一个潜在问题是,如果 MyBase 发生更改,那么init会很好,因为它调用“super”,但eq不会更新其行为。
所以我尝试用“type(super)”或“type(super())”替换“MyBase”,但这些不引用超类,它们引用对象“super”的类。
请注意,此问题不同于:
获取父类名? 获取Python 3等中未绑定方法对象的定义类。
因为一旦对象被初始化,他们就会寻找父类。
我想我应该能够通过运行 MRO 找到超级类。但这似乎是一个糟糕的解决方案,因为我不是在寻找整个继承树,我只是想知道超类的类型。
有没有办法从“超级”中提取这些信息?
首先,你要在遇到不支持的类型时返回NotImplemented
,__eq__
这样Python也可以给第二个操作数一个参与相等测试的机会。来自Python 数据模型文档:
如果数字方法和丰富的比较方法没有实现所提供操作数的操作,则应返回此值。(然后解释器将尝试反射操作,或其他一些后备,具体取决于操作员。)
您的代码实际上应该只委托给super().__eq__()
何时other
不是同一类型的实例,这里不需要测试基类型;基类应该已经负责测试正确的类型或协议。
接下来,您可以使用Python 3__class__
闭包来访问定义了方法的类;每当您在嵌套在类定义内的函数定义中使用super()
或时,Python 都会添加此闭包:__class__
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)
Run Code Online (Sandbox Code Playgroud)
请注意,我使用isinstance()
而不是type()
测试,您希望的子类MyDerived_2
继承此行为。
您还可以依赖鸭子类型,而不是测试特定的类层次结构;如果另一个对象具有正确的属性名称,则假设它可以用于与以下对象进行比较:
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)
Run Code Online (Sandbox Code Playgroud)