How does a method of a subclass become a method of the base class?

Jen Kris jenkris at tutanota.com
Sun Mar 26 19:53:49 EDT 2023


Cameron, 

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.  

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

Because EqualityConstraint is a subclass of BinaryConstraint, the init method of BinaryConstraint is called first.  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>>

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. 

But that brings up a new question.  I can create a class instance with x = BinaryConstraint(), but what happens when I have a line like "EqualityConstraint(prev, v, Strength.REQUIRED)"? Is it because the only method of EqualityConstraint is execute(self)?  Is execute a special function like a class __init__?  I’ve done research on that but I haven’t found an answer. 

I’m asking all these question because I have worked in a procedural style for many years, with class work limited to only simple classes, but now I’m studying classes in more depth. The three answers I have received today, including yours, have helped a lot. 

Thanks very much. 

Jen


Mar 26, 2023, 22:45 by cs at cskk.id.au:

> On 26Mar2023 22:36, Jen Kris <jenkris at tutanota.com> wrote:
>
>> At the final line it calls "satisfy" in the Constraint class, and that line calls choose_method in the BinaryConstraint class.  Just as Peter Holzer said, it requires a call to "satisfy." 
>>
>> My only remaining question is, did it select the choose_method in the BinaryConstraint class instead of the choose_method in the UrnaryConstraint class because of "super(BinaryConstraint, self).__init__(strength)" in step 2 above? 
>>
>
> Basicly, no.
>
> You've omitting the "class" lines of the class definitions, and they define the class inheritance, _not "__init__". The "__init__" method just initialises the state of the new objects (which has already been created). The:
>
>  super(BinaryConstraint,_ self).__init__(strength)
>
> line simply calls the appropriate superclass "__init__" with the "strength" parameter to do that aspect of the initialisation.
>
> You haven't cited the line which calls the "choose_method" method, but I'm imagining it calls "choose_method" like this:
>
>  self.choose_method(...)
>
> That searchs for the "choose_method" method based on the method resolution order of the object "self". So if "self" was an instance of "EqualityConstraint", and I'm guessing abut its class definition, assuming this:
>
>  class EqualityConstraint(BinaryConstraint):
>
> Then a call to "self.choose_method" would look for a "choose_method" method first in the EqualityConstraint class and then via the BinaryConstraint class. I'm also assuming UrnaryConstraint is not in that class ancestry i.e. not an ancestor of BinaryConstraint, for example.
>
> The first method found is used.
>
> In practice, when you define a class like:
>
>  class EqualityConstraint(BinaryConstraint):
>
> the complete class ancestry (the addition classes from which BinaryConstraint inherits) gets flatterned into a "method resultion order" list of classes to inspect in order, and that is stored as the ".__mro__" field on the new class (EqualityConstraint). You can look at it directly as "EqualityConstraint.__mro__".
>
> So looking up:
>
>  self.choose_method()
>
> looks for a "choose_method" method on the classes in "type(self).__mro__".
>
> Cheers,
> Cameron Simpson <cs at cskk.id.au>
> -- 
> https://mail.python.org/mailman/listinfo/python-list
>



More information about the Python-list mailing list