简体   繁体   中英

Accidentally calling an ovverriden method from base class's __init__

This program seems to do everything by the book, yet this issue cropped up: while a base class was being init'ed a member method was called that is overriden in the derived class and assumes that the derived class has been constructed.

Is there some best practice to protect against this?

#!/usr/bin/env python3

class A:
    def __init__(self):
        self.ax = 1
        print(self)

    def __repr__(self):
        return "{} ax: {}".format(self.__class__.__name__, self.ax)


class B(A):
    def __init__(self):
        super().__init__()
        self.bx = 10

    def __repr__(self):
        return super().__repr__() + " bx: {}".format(self.bx)


if __name__ == "__main__":
    B()

And here's the error:

AttributeError: 'B' object has no attribute 'bx'

Generally, unless you really know what you are doing, you want to call the superclass initialization after everything your class needs to do is done. Same with this example, repr is trying to print self.bx before you initialize it. If you do

class B(A):
    def __init__(self):
        self.bx = 10
        super().__init__()

    def __repr__(self):
        return super().__repr__() + " bx: {}".format(self.bx)

it works as expected

Edited:

Instead of doing computation on __init__ , one idea may be to do that in a factory function/classmethod.

Example instead of doing:

class A:
    def __init__(self, a, b):
        self.a = a
        self.b = b
        self.initialize()

    def initialize(self):
        # do some things

Do:

class A:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    @classmethod
    def from_a_b(cls, a, b):
        instance = cls(a, b)
        instance.initialize()
        return instance

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM