获取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()。