如何扩展类方法

10 投票
2 回答
21752 浏览
提问于 2025-04-18 18:15

SubClassASubClassB都是Base类的子类,也就是说它们都从同一个Base类继承而来。因为getInfo()这个方法是在Base类里面定义的,所以这个方法可以被SubClassASubClassB共享。当你调用getInfo()方法时,它会返回self.attr这个变量的值,这个变量在A和B两个子类之间是共享的。现在我想要“扩展”这个方法。也就是说,当通过instanceA.getInfo()来调用时,除了返回self.attr,还希望它能返回self.attrA。同样的,如果使用instanceB.getInfo(),那么除了返回self.attr,还应该返回self.attrB。那么,如何才能扩展Base类的getInfo()方法,使得它可以针对SubClassASubClassB这两个子类进行“定制”呢?

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 个回答

0

还有一个额外的选项是,你可以同时返回两个属性:

return self.attr, self.attrA

另外,除了 onethreeseven 提到的方法,你还可以把 attr 数据本身和你的 attrA 数据结合起来,比如放在一个列表里或者添加到一个字符串中,然后返回这个结果。

或者你可以递归地调用你已有的两个方法,或者使用装饰器来实现,这样也是可以的。你可以直接访问(并重新定义)一个类的定义。

你可以通过 func 属性获取原始函数:ClassName.function_name = decorator(ClassName.function_name.__func__)

来自 如何在 Python 中“事后”给函数添加装饰器?(Martijn Pieters 在函数/装饰器领域回答问题)

28

简单来说,在子类中定义一个叫做 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 来说并不是这种情况。

撰写回答