【问题标题】:Python 3 Inheritance IssuePython 3 继承问题
【发布时间】:2019-04-10 11:01:06
【问题描述】:

我是 Python 新手,在继承和使用方面有困难 超级()

下面的代码给了我这个错误

发生异常:AttributeError 'ObjB' 对象没有属性 'job'

但我不确定为什么 as job 是 ObjB 的一个属性

测试代码是这样的..

class ObjA():
    def __init__(self, astr):
        self.name = astr
        self.decorate()

    def decorate(self):
        self.name = '['+self.name+']'

class ObjB(ObjA):
    def __init__(self, aname, ajob):
        super().__init__(aname)
        self.job = ajob

    def decorate(self):
        super().decorate()
        self.name = self.name + ' is a ' + self.job

test = ObjA('Fred')
print(test.name)

test2 = ObjB('Fred', 'Baker')
print(test2.name)

我期待的是这个

[Fred]
[Fred] is a Baker

【问题讨论】:

    标签: python python-3.x class inheritance super


    【解决方案1】:

    关键是当你在子类中使用super调用基类中的__init__时,传递给__init__self是子类ObjB的实例而不是比ObjA。所以ObjA__init__中的self.decorate()实际上调用了ObjB中的decorate方法,这就是job没有定义的原因。

    super().__init__ 函数如下:ObjA.__init__(test2)

    以下来自Python docs关于继承

    派生类可以覆盖其基类的方法。由于方法在调用同一对象的其他方法时没有特殊权限,因此基类的方法调用同一基类中定义的另一个方法可能最终会调用覆盖它的派生类的方法。

    【讨论】:

    • 好的。创建ObjB时,我想要的是ObjA的__init__调用ObjA的装饰方法和ObjB的init调用的ObjB的装饰方法有没有办法实现这个或我需要重组我的类以不从 __init__ 调用 decorate 方法吗?
    • @CHaste 一种方法是在您的__init__ 方法中使用ObjA.decorate(self),但这是一种不好的做法。我认为你需要一个清晰的结构设计。如果ObjA 是为了继承而方法要被覆盖,那么在调用ObjA 中的方法时要小心,因为它可能会被子类覆盖。
    【解决方案2】:

    在您的ObjB.__init__() 方法中,您在设置self.job = ajob 之前调用super().__init__(aname),因此当调用decorate 方法时,self.job 尚未设置。尝试在 __init__() 方法中将 self.job = ajob 移到前面,例如:

    class ObjB(ObjA):
        def __init__(self, aname, ajob):
            self.job = ajob
            super().__init__(aname)
    

    解决问题的另一种方法是完全消除decorate() 方法:

    class ObjA():
        def __init__(self, astr):
            self.name = '['+astr+']'
    
    
    class ObjB(ObjA):
        def __init__(self, aname, ajob):
            super().__init__(aname)
            self.job = ajob
            self.name = self.name + ' is a ' + self.job
    

    【讨论】:

    • 是的,这确实解决了问题,但这是由于我没想到 ObjA 上的 __init__ 会调用 ObjB 上的 decorate 方法。这可以避免吗?
    • 我在上面编辑了我的答案,以包含另一种完全消除 decorate() 方法的可能性。
    猜你喜欢
    • 2011-08-25
    • 2010-10-30
    • 2011-12-04
    • 1970-01-01
    • 2023-03-25
    • 2012-08-08
    相关资源
    最近更新 更多