简体   繁体   中英

How to use the attributes of a child class in methods called by its parent's __init__

I want to overwrite some default class attributes in inherited classes, which influence the functionality of intermediate classes. eg in the following snippet, in the intermediate Child 's initialisation, I want the call to internal_setting to rely on _a as set by GrandChild , so that the outputs are both that .

class Parent():
    def __init__(self):
        # set a basic parameter
        self._a = True
    
    def externally_called_method(self):
        # uses correct self._a 
        if self._a:
            self.externally_set =  "this"
        else:
            self.externally_set = "that"
        
class Child(Parent):
    def __init__(self):
        super().__init__()
        self.internal_settings()
        
    def internal_settings(self):
        # uses most recent self._a
        if self._a:
            self.internally_set = "this"
        else:
            self.internally_set = "that"
            
class GrandChild(Child):
    def __init__(self):
        super().__init__()
        self._a = False

        
g = GrandChild()
g.externally_called_method()

print("Internally set: {}".format(g.internally_set))
print("Externally set: {}".format(g.externally_set))
>>> Internally set: this
>>> Externally set: that

Is it possible that methods called by the __init__ of an intermediate ( Child ) class uses the attribute of the GrandChild class?

I know I could just make _a a param, but I prefer not to since in the real program, the Parent class has a large number of attributes which can be overwritten by subclasses. A secondary question is whether this is a bad approach in general, ie facilitating customisation by a ladder of inherited classes, where attributes can be set according to the use-case.

Once you are running a method, it will run thoughtfully - if Parent.__init__ is called to initialize parameters, and it is called from Child.__init__ , there is no way you can change that from GrandChild.__init__ : it can, obviously, just run Child.__init__ as a single call.

However, if you break you classes in more components, that is easily fixable.

If the parameters can be class attributes, it is as easy as just declaring them outside __init__ , and the natural inheritance rules of OO will work for you:

    
class Parent():
    _a = True
    def __init__(self):
        # basic parameters are set as class attributes.
        ...

...



class GrandChild(Child):
    _a = False
    def __init__(self):
        
        super().__init__()

If they can't be straight class attributes (due to needing from runtime input that is passed to __init__ , all you have to do is to break-up the responsibilities of your class in more methods (one can call these methods "slots") so, __init__ instead of having the responsibility to initialize all parameters, then call the internal_settings - can instead delegate the responsibility of initializing the parameters to another method. In that way, you can override that method on the GrandChild:

class Parent():
    def __init__(self):
        self._set_parameters()

    def _set_parameters(self):
        self._a = True
    
    def externally_called_method(self):
        # uses correct self._a 
        if self._a:
            self.externally_set =  "this"
        else:
            self.externally_set = "that"
        
class Child(Parent):
    def __init__(self):
        super().__init__()
        self.internal_settings()
    ...
        
class GrandChild(Child):
    def __init__(self):
        super().__init__()

    def _set_parameters(self):
        self._a = False

And, of course, your problem is more complicated than this - but all you have to do is to move all initialisations or tasks that could be individually overriden to separate methods - in that way you just replace any setup as needed in the child classes.

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