Child Class constructor using super() - getting un

2019-07-21 02:06发布

问题:

I'm trying to create classmethod constructors for a child class, but I cannot initialize the instance properly.

I have read many blogs and answers on this site and even tried exactly what some other people have posted, still to no avail. Hopefully I'm missing something really simple. Basic example of what I'm trying:

class A(object):
    def __init__(self, foo):
        self.foo = foo

class B(A):

    @classmethod
    def make_new(cls):
        super(B, cls).__init__('bar')

foobar = B.make_new()

I keep getting unbound method error:

TypeError: unbound method __init__() must be called with B instance as first argument (got str instance instead)

回答1:

The __init__ method is a regular instance method, not a class method. It needs the instance it is going to initialize to already have been created when it is called. Your current code is failing in exactly the same way that A.__init__("foo") would fail (it's not the fault of super).

I suspect you wanted to be calling __new__ rather than __init__. The __new__ method is the actual "constructor" method that is responsible for creating the instance (usually by delegating the actual creation step to object.__new__). You don't need to use super either, since you've not overridden the __new__ method that you inherited (from object, since A doesn't override it either).

But you don't actually need to do that either. You can just call the cls argument your classmethod been passed. Calling a class is the normal way to construct instances:

class B(A):
    @classmethod
    def make_new(cls):
        return cls("bar")  # note that you also need to `return` the instance you create!

If the purpose of the class method is to avoid running B.__init__, you might want something like:

class B(A):
    @classmethod
    def make_new(cls):
        self = cls.__new__(cls)
        super(B, self).__init__('bar')
        return self