python 中的继承 - 如何使一个方法既是类方法又是常规方法?

inheritance in python - how to make a method both a classmethod and a regular method?

假设我在class中有一个方法,其结构如下:

class TestClass(object):
   ...
   def __init__(self, ...)
       ...
       self.var1 = ...
       self.var2 = ...
       ...
   ...
   def xyz(self, other)
       if isinstance(other, TestClass):
            ...
            self.var1 = ...
            ...
       else:
            ...
            self.var2 = ...
            ...

现在假设我想写另一个 class NewTestClass 继承自 TestClass (即 class NewTestClass(TestClass): ... )。

方法 xyz 的一个问题是它明确检查 other 变量是否是 TestClass 的实例并且它还引用实例的属性(即 self.var1, self.var2).

(a) 如何重写方法 xyz 以便在继承时(在 NewTestClass 中),if 语句的行为类似于 if isinstance(other, NewTestClass): ...(我不不必在 NewTestClass) 中重写方法 xyz

(b) 同样,假设我在 TestClass 中有另一个 method 引用 TestClass 中的 staticmethod,例如:

@staticmethod
def abc(x):
    ...
    val = ...
    ...
    return val

def mnp(self, ...):
    ...
    x1 = ...
    self.var1 = TestClass.abc(x1)
    ...

此处,方法 mnp 使用 staticmethod of TestClass(即本例中的 TestClass.abc)。我如何重写 TestClass.abc,以便当 NewTestClass 继承 TestClass 时,它得到一个方法 mnpself.var = 行视为等同于 self.var1 = NewTestClass.abc(x1)(而且我不必在 NewTestClass 中重写方法 mnp)?

你可以做一些丑陋的反射来让它工作,但这不是正确的做法。如果 classes 想自然地相互延伸 - 做,如果不是 - 不要。

就是说,您可以做的一件事是更改当前的实现,而不是分配一个 var - 调用另一个这样做的函数,并在每个 class 中实现此函数以修改正确的变量。

例如,更改:

def xyz(self, other)
   if isinstance(other, TestClass):
        ...
        self.var1 = ...
        ...
   else:
        ...
        self.var2 = ...
        ...

至:

def xyz(self, other)
   if isinstance(other, TestClass):
        ...
        self.modifyVar(value)
        ...
   else:
        ...
        self.var2 = ...
        ...

然后 class 您将实现:

def modifyVar(self, value):
    self.var1 = value

在另一个 class 中,您将拥有:

def modifyVar(self, value):
    self.var2 = value

这个答案涵盖了两种情况(静态和非静态函数)。

一)

def xyz(self, other):
    if isinstance(other, self.__class__):
       ...

b) 您可以使用 self:

调用静态 class 方法
    def mnp(self, ...):
        ....
        self.var1 = self.abc(...)

对于(a)部分,您需要检查other是否是与self相同的class的实例:

class TestClass(object):
  def xyz(self, other):
    if isinstance(other, self.__class__):
      ...
      self.var1 = ...
      ...
    else:
      ...
      self.var2 = ...
      ...

通常认为 'pythonic' 尽可能避免 isinstance 这种逻辑。考虑使用 Python 的鸭子类型。以下示例不会完全满足您的需要,因为这两个属性都存在于您的 class 中。但是,如果您为实际代码选择了适当的异常,则此技术将起作用。

class TestClass(object):
  def xyz(self, other):
    try:
      self.var1 = ...   # The minimum code required to raise the exception
    except AttributeError:
      self.var2 = ...
    else:
      pass              # Any other code if the exception is not raised

Python 的异常处理是轻量级的,旨在以这种方式使用。如果传入意外(可能尚未考虑),它会使您的代码更具弹性。

对于(b)部分,调用静态方法时不需要指定class。它可以在实例 (self) 上调用。

class TestClass(object):
  @staticmethod
  def abc(x):
    return x  # Do something useful

  def mnp(self, x):
    self.var1 = self.abc(x)

现在,当您在派生的 class 中声明一个新的静态方法时,它将被正确调用:

class NewTestClass(TestClass):
  @staticmethod
  def abc(x):
    return x * 2  # Do something else useful

a = NewTestClass()
a.mnp(1)
assert a.var1 == 2  # because NewTestClass.abc was called by mnp