【问题标题】:python class inheritance: constructor of derived class issuepython类继承:派生类的构造函数问题
【发布时间】:2012-11-21 21:53:17
【问题描述】:

我有两个类:基类 A 和派生类 B。在 B 的构造函数中,我尝试使用 A 的构造函数来初始化实例。为什么派生类的构造函数中赋值“self = A(x)”不起作用?

class A:
    def __init__(self, x=0):
        print "constructing A"
        self.x = x

    def printx(self):
        print "x =",self.x 

class B(A):
    def __init__(self,x):
        A.__init__(self)
        print "constructing B"
        self = A(x)
        self.printx()


b = B(2)
b.printx()

输出:

constructing A
constructing B
constructing A
x = 2
x = 0

【问题讨论】:

  • 你到底想做什么?即,您的预期输出是什么?

标签: python class inheritance constructor derived


【解决方案1】:

你不想调用B.__init__中的构造函数,你应该将x传递给A.__init__

class A:
    def __init__(self, x=0):
        print "constructing A"
        self.x = x
    def printx(self):
        print "x =",self.x 

class B(A):
    def __init__(self,x):
        A.__init__(self, x)
        print "constructing B"
        self.printx()

【讨论】:

    【解决方案2】:

    在 Python 中,将变量名(如 self)视为“指向”或“引用”值。当您创建B 的实例时:

    b = B(2)
    

    调用B.__init__ 方法时已将变量self 分配给B 的早期实例。现在,在这个方法里面,当 Python 到达

            self = A(x)
    

    变量self 被重新分配给A 的新实例。 B 的实例仍然存在; self 只是不再指向它。

    请注意,self 与 Python 中的任何其他变量一样是一个变量。 (self 不是关键字,只是约定方法的第一个参数称为self。)


    顺便说一下,要用x的值初始化self,使用

    class B(A):
        def __init__(self,x):
            A.__init__(self, x)    # <-- Note the x
            print "constructing B"
            self.printx()
    

    然后

    b = B(2)
    b.printx()
    

    产量

    constructing A
    constructing B
    x = 2
    x = 2
    

    当类有备用构造函数时,例如getA,Python 中的典型模式是使用类方法:

    class A(object):
        def __init__(self, x=0):
            print "constructing A"
            self.x = x
    
        def printx(self):
            print "x =",self.x 
    
        @classmethod
        def getA(cls, x):
            print('constructing getA')
            self = cls(x)
            self.y = 1
            return self
    

    现在用类方法getA 来创建A 的实例,你会说

    a = A.getA(x)
    

    A作为第一个参数传递给类方法getA,并存储在变量cls中。

    以这种方式(而不是使用工厂函数getA)这样做的美妙之处在于,如果您像这样子类化A

    class B(A):
        def __init__(self,x):
            A.__init__(self, x)
            print "constructing B"
            self.printx()
    

    那么您也可以使用getA 类方法创建B 的实例:

    b = B.getA(2)
    

    产量

    constructing getA
    constructing A
    constructing B
    x = 2
    

    print(type(b))
    print(b.y)
    

    产量

    <class '__main__.B'>  # b is an instance of B
    1   # showing the y attribute has been set.
    

    【讨论】:

    • 谢谢@unutbu 和@jfaller!那么 - 我怎样才能为'self'分配一个值而不将它重新分配给A的新实例?我问的原因是我有一个“工厂”函数getA(x),它返回一个A类型的对象。有什么办法可以在B的构造函数中使用self = getA(x)之类的东西吗?
    • 不要尝试重新分配self。而是想办法修改self(改变它的属性)。我已经编辑了我的帖子以展示一种方法。
    • 非常感谢!这很有帮助。
    猜你喜欢
    • 2014-12-19
    • 2012-12-19
    • 1970-01-01
    • 2015-11-03
    • 2017-02-25
    • 2021-03-26
    • 1970-01-01
    • 2016-05-23
    • 2011-12-29
    相关资源
    最近更新 更多