python中的继承 - 如何使方法同时成为classmethod和常规方法?

时间:2015-04-16 05:51:16

标签: python inheritance python-3.x static-methods

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

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

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

方法xyz的一个问题是它显式检查other变量是否是TestClass的实例,它还引用了实例的属性(即{{1} },self.var1)。

(a)如何重写方法self.var2,以便在继承(xyz)后,NewTestClass语句的行为类似于if(我不会&#39} ; t必须在if isinstance(other, NewTestClass): ...)内重写方法xyz

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

TestClass

此处,方法@staticmethod def abc(x): ... val = ... ... return val def mnp(self, ...): ... x1 = ... self.var1 = TestClass.abc(x1) ... 使用mnp的{​​{1}}(在此示例中为staticmethod)。如何重写TestClass,以便在TestClass.abc继承TestClass.abc时,它会获得一个方法NewTestClass,将TestClass行视为等效{{1} (并且我不必在mnp内重写方法self.var =)?

3 个答案:

答案 0 :(得分:2)

A)

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

b)您可以使用self

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

答案 1 :(得分:2)

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

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

它通常被认为更多' pythonic'在可能的情况下避免isinstance这种逻辑。考虑使用Python的鸭子打字。以下示例并不完全符合您的需要,因为您的类中存在这两个属性。但是,如果您为实际代码选择了适当的例外,这种技术将起作用。

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)部分,在调用静态方法时不需要指定类。它可以在实例(self)上调用。

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

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

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

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

答案 2 :(得分:0)

你可以做一些丑陋的反思,让它发挥作用,但这不是正确的事情。如果课程假设自然地相互延伸 - 如果没有,那就去做吧 - 不要。

那就是说,你可以做的一件事就是改变当前的实现,而不是分配一个var来调用另一个函数,并在每个类中实现这个函数来修改正确的变量。

例如,更改:

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 = ...
        ...

然后在一个课程中实施:

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

在另一个课程中你会:

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

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