How does a method of a subclass become a method of the base class?
Cameron Simpson
cs at cskk.id.au
Sun Mar 26 21:03:29 EDT 2023
On 27Mar2023 01:53, Jen Kris <jenkris at tutanota.com> wrote:
>Thanks for your reply. You are correct about the class definition
>lines – e.g. class EqualityConstraint(BinaryConstraint). I didn’t post
>all of the code because this program is over 600 lines long. It's
>DeltaBlue in the Python benchmark suite.
Doubtless. But the "class ...:" line is the critical thing.
>I’ve done some more work since this morning, and now I see what’s happening. But it gave rise to another question, which I’ll ask at the end.
>
>The call chain starts at
>
> EqualityConstraint(prev, v, Strength.REQUIRED)
>
>The class EqualityConstraint is a subclass of BinaryConstraint. The entire class code is:
>
> class EqualityConstraint(BinaryConstraint):
> def execute(self):
> self.output().value = self.input().value
Ok, so it is effectively a BinaryConstraint with a single customised
execute() method.
>Because EqualityConstraint is a subclass of BinaryConstraint, the init method of BinaryConstraint is called first.
That is courtesy of the MRO: EqualityConstraint has no __init__, so the
one found in BinaryConstraint is found and used.
>During that initialization (I showed the call chain in my previous
>message), it calls choose_method. When I inspect the code at
>"self.choose_method(mark):" in PyCharm, it shows:
>
> <bound method BinaryConstraint.choose_method of <Trans_01_DeltaBlue.EqualityConstraint object at 0x7f7ac09c6ee0>>
This says that it found found the choose_method method in the
BinaryConstraint class definition, but that it is _bound_ to the
EqualityConstraint instance you're using (self).
>As EqualityConstraint is a subclass of BinaryConstraint it has bound the choose method from BinaryConstraint, apparently during the BinaryConstraint init process, and that’s the one it uses. So that answers my original question.
Incorrectly, I think.
__init__ does _nothing_ about other methods, if you mean "__init__" in
the sentence above.
The class definition results in an EqualityConstraint.__mro__ list of
classes, which is where _every_ method is looked for _at call time_.
>But that brings up a new question. I can create a class instance with
>x = BinaryConstraint(),
That makes an instance of EqualityConstraint.
>but what happens when I have a line like "EqualityConstraint(prev, v,
>Strength.REQUIRED)"?
That makes an instance of EqualityConstraint.
>Is it because the only method of EqualityConstraint is execute(self)?
I don't know what you're asking here.
>Is execute a special function like a class __init__?
No. It's just a method.
In a sense, __init__ isn't very special either. It is just _called_
during new instance setup as the final step. By that time, self is a
fully set up instance of... whatever and the __init__ function is just
being called to do whatever initial attribute setup every instance of
that class needs.
Python doesn't magicly call _all_ the __init__ methods of all the
superclasses; it calls the first found. So for an EqualityConstraint it
finds the one from BinaryConstraint because EqualityConstraint does not
provide an overriding one of its own.
If EqualityConstraint _did_ provide one, it might typically be
structured as:
class EqualityConstraint(BinaryConstraint):
def __init__(self, prev, v, strength, something_extra):
super().__init__(prev, v, strength)
self.extra = something_extra
So:
- Python only calls _one_ __init__ method
- in the example above, it finds one in EqualityConstraint and uses it
- because Python calls _only_ that, in order to _also_ do the normal
setup a BinaryConstraint needs, we pass the parameters used by
BinaryConstraint to the new __init__ up the chain by calling
super().__init__(BinaryConstraint-parameters-here)
- we do our own special something with the something_extra
That super().__init__() call is the _only_ thing which arranges that
superclass inits get to run. This givens you full control to sompletely
replace some superclass' init with a custom one. By calling
super().__init__() we're saying we not replacing that stuff, we're
running the old stuff and just doing something additional for our
subclass.
Cheers,
Cameron Simpson <cs at cskk.id.au>
More information about the Python-list
mailing list