如何扩展类方法
SubClassA
和SubClassB
都是Base
类的子类,也就是说它们都从同一个Base
类继承而来。因为getInfo()
这个方法是在Base
类里面定义的,所以这个方法可以被SubClassA
和SubClassB
共享。当你调用getInfo()
方法时,它会返回self.attr
这个变量的值,这个变量在A和B两个子类之间是共享的。现在我想要“扩展”这个方法。也就是说,当通过instanceA.getInfo()
来调用时,除了返回self.attr
,还希望它能返回self.attrA
。同样的,如果使用instanceB.getInfo()
,那么除了返回self.attr
,还应该返回self.attrB
。那么,如何才能扩展Base
类的getInfo()
方法,使得它可以针对SubClassA
和SubClassB
这两个子类进行“定制”呢?
class Base(object):
def __init__(self):
super(Base, self).__init__()
self.attr='Attr'
def getInfo(self):
info=self.getAttr()
return info
def getAttr(self):
return self.attr
class SubClassA(Base):
def __init__(self):
super(SubClassA, self).__init__()
self.attrA='attrA'
def getAttrA(self):
return self.attrA
class SubClassB(Base):
def __init__(self):
super(SubClassB, self).__init__()
self.attrB='attrB'
def getAttrB(self):
return self.attrB
instanceA=SubClassA()
instanceB=SubClassB()
print instanceA.getInfo()
print instanceB.getInfo()
2 个回答
还有一个额外的选项是,你可以同时返回两个属性:
return self.attr, self.attrA
另外,除了 onethreeseven 提到的方法,你还可以把 attr 数据本身和你的 attrA 数据结合起来,比如放在一个列表里或者添加到一个字符串中,然后返回这个结果。
或者你可以递归地调用你已有的两个方法,或者使用装饰器来实现,这样也是可以的。你可以直接访问(并重新定义)一个类的定义。
你可以通过 func 属性获取原始函数:
ClassName.function_name = decorator(ClassName.function_name.__func__)
。
来自 如何在 Python 中“事后”给函数添加装饰器?(Martijn Pieters 在函数/装饰器领域回答问题)
简单来说,在子类中定义一个叫做 getInfo
的方法。如果需要的话,可以使用 super
(就像你在构造函数中做的那样)来获取基类的 getInfo()
的结果,并根据需要进行处理。
具体来说,当你有一个类 C
的实例 c
,并想要查看一个属性 c.attr
时,Python 会在一系列地方查找这个属性。特别是,它会先在子类中查找,然后再去基类中查找。因此,下面的代码
class Base(object):
def method(self):
return "I'm a base object!"
class Derived(Base):
def method(self):
return "I'm a derived object!"
obj = Derived()
print obj.method()
会输出 "I'm a derived object!",因为 Python 在 Derived
类中找到了 method
,所以就不会再去 Base
类中查找了。
你提到需要在你的 Derived
对象中调用 Base.method
。这就是 super
的用武之地。super(Derived, self).method()
会找到并调用 Base.method
,并作用于 self
。你在构造函数中已经在做这个了。
举个例子:
class Computer(object):
def boot_message(self):
return 'I am a computer'
class AppleComputer(Computer):
def boot_message(self):
return super(AppleComputer, self).boot_message() + ' with a really shiny logo'
我们通过获取 Computer.boot_message
的结果并根据需要进行修改,来避免重复工作。
需要注意的是,super(Base, self).__init__()
这一行并不是必须的;一般来说,只有当基类的 __init__()
做了一些派生类的 __init__()
想要完成的工作,而又不想重复代码时,这种调用才是有意义的,但对于 object
来说并不是这种情况。