继承虚拟 class 方法 - 如何从基础 class 调用它?

Inheriting a virtual class method - how to call it from base class?

B继承自A。假设 B 的某些行为依赖于 class 属性 cls_x 并且我们希望在构造 B 对象期间设置这种依赖性。由于这不是一个简单的操作,我们希望将其包装在构造函数将调用的 class 方法中。示例:

class B(A):
  cls_x = 'B'

  @classmethod
  def cm(cls):
    return cls.cls_x

  def __init__(self):
    self.attr = B.cm()

问题:cm__init__ 将始终做相同的事情,并且它们的行为必须在每个派生的 class 中保持相同。因此,我们希望将它们都放在基础 class 和 中,而不是 在任何派生的 class 中定义它。唯一的区别是 cm 的调用者 - AB(或 B1B2 中的任何一个,每个继承自 A ), 无论正在建造什么。所以我们想要的是这样的:

class A:
  cls_x = 'A'

  @classmethod
  def cm(cls):
    return cls.cls_x

  def __init__(self):
    self.attr = ClassOfWhateverIsInstantiated.cm()  #how to do this?

class B(A):
  cls_x = 'B'

我觉得这要么是我在 Python 的继承机制中遗漏了一些非常简单的东西,要么整个问题应该完全不同地处理。

这与 this 问题不同,因为我不想重写 class 方法,而是将其实现完全移至基础 class。

对于 ClassOfWhateverIsInstantiated 你可以只使用 self:

class A:
  cls_x = 'A'

  @classmethod
  def cm(cls):
    return cls.cls_x

  def __init__(self):
    self.attr = self.cm()  # 'self' refers to B, if called from B

class B(A):
  cls_x = 'B'

a = A()
print(a.cls_x) # = 'A'
print(A.cls_x) # = 'A'

b = B()
print(b.cls_x) # = 'B'
print(B.cls_x) # = 'B'

要理解这一点,只要记住 class B 继承了 class A 的 方法 。所以当 __init__() 被调用时B的实例化,它在class B的上下文中被调用,self指的是

这样看:你的问题本质上是 "How do I get the class of an instance?"。该问题的答案是使用 type 函数:

ClassOfWhateverIsInstantiated = type(self)

但你甚至不需要这样做,因为class方法可以直接通过实例调用:

def __init__(self):
    self.attr = self.cm()  # just use `self`

这是可行的,因为 class 方法会自动为您查找实例的 class。来自 the docs:

[A classmethod] can be called either on the class (such as C.f()) or on an instance (such as C().f()). The instance is ignored except for its class.