我有两个类
A
和 B
并且都有一个方法 get_type()
返回一个字符串,并且在两个类的 __init__()
中调用它来设置实例属性 self.type
。现在有一个继承自 A
和 B
的子类,在它的 __init__()
中,它需要一个 A
或 B
的实例作为参数。根据它是用 A
还是 B
的实例实例化,我调用相应的父级 __init__()
。大概是因为多重继承的查找顺序,总是调用get_type()
父级的A
方法,即使C
是用B
的实例实例化的。见以下代码:
class A:
def __init__(self):
self.type = self.get_type()
def get_type(self):
return 'A'
class B:
def __init__(self):
self.type = self.get_type()
def get_type(self):
return 'B'
class C(A, B):
def __init__(self, instance):
if isinstance(instance, A):
A.__init__(self)
print('Inheriting from A')
else:
B.__init__(self)
print('Inheriting from B')
a = A()
b = B()
c = C(b)
print(a.type, b.type, c.type)
>>> Inheriting from B
>>> A B A
所以我希望
c.type
是“B”,因为它继承自 B
类。我可以使用 super()
函数来获得我想要的行为吗?
为什么你分开做那件事,这就是你要的:
当您有冲突(或潜在冲突)的方法名称时,Python 的避免机制是在方法名称前加上两个下划线 (
__
)。大多数关于 Python 的文章和第 3 方文档都将此称为“在 Python 中创建私有属性/方法的方法”。事实并非如此:Python 根本不使用私有属性,而是为了约定(使用单个 _
作为前缀。
使用两个下划线而不是一个下划线,触发方法或属性的内部名称转换,以透明的方式将类名作为前缀添加到目标方法。这称为“名称修改”。
就您的代码而言,它将开箱即用,无需进一步更改。如果您检查正在运行的代码(例如
print(dir(self))
),您将看到您的方法将分别命名为A._A__get_type
和B._B__get_type
(这两种方法都将出现在C
中)
class A:
def __init__(self):
self.type = self.__get_type()
def __get_type(self):
return 'A'
class B:
def __init__(self):
self.type = self.__get_type()
def __get_type(self):
return 'B'
但是,看到
C
中的任何方法都无法“看到”.get_type
:该方法现在对每个超类都是“私有的”。两者都可以从 C 访问它们的转换名称,如果明确使用,很难。