Thanks to Richard Damon and Peter Holzer for your replies. I'm working through the call chain to understand better so I can post a followup question if needed.
Thanks again. Jen Mar 26, 2023, 19:21 by rich...@damon-family.org: > On 3/26/23 1:43 PM, Jen Kris via Python-list wrote: > >> The base class: >> >> >> class Constraint(object): >> >> def __init__(self, strength): >> super(Constraint, self).__init__() >> self.strength = strength >> >> def satisfy(self, mark): >> global planner >> self.choose_method(mark) >> >> The subclass: >> >> class UrnaryConstraint(Constraint): >> >> def __init__(self, v, strength): >> super(UrnaryConstraint, self).__init__(strength) >> self.my_output = v >> self.satisfied = False >> self.add_constraint() >> >> def choose_method(self, mark): >> if self.my_output.mark != mark and \ >> Strength.stronger(self.strength, self.my_output.walk_strength): >> self.satisfied = True >> else: >> self.satisfied = False >> >> The base class Constraint doesn’t have a "choose_method" class method, but >> it’s called as self.choose_method(mark) on the final line of Constraint >> shown above. >> >> My question is: what makes "choose_method" a method of the base class, >> called as self.choose_method instead of UrnaryConstraint.choose_method? Is >> it super(UrnaryConstraint, self).__init__(strength) or just the fact that >> Constraint is its base class? >> >> Also, this program also has a class BinaryConstraint that is also a subclass >> of Constraint and it also has a choose_method class method that is similar >> but not identical: >> >> def choose_method(self, mark): >> if self.v1.mark == mark: >> if self.v2.mark != mark and Strength.stronger(self.strength, >> self.v2.walk_strength): >> self.direction = Direction.FORWARD >> else: >> self.direction = Direction.BACKWARD >> >> When called from Constraint, it uses the one at UrnaryConstraint. How does >> it know which one to use? >> >> Thanks, >> >> Jen >> > > Perhaps the key point to remember is that when looking up the methods on an > object, those methods are part of the object as a whole, not particually > "attached" to a given class. When creating the subclass typed object, first > the most base class part is built, and all the methods of that class are put > into the object, then the next level, and so on, and if a duplicate method is > found, it just overwrites the connection. Then when the object is used, we > see if there is a method by that name to use, so methods in the base can find > methods in subclasses to use. > > Perhaps a more modern approach would be to use the concept of an "abstract > base" which allows the base to indicate that a derived class needs to define > certain abstract methods, (If you need that sort of support, not defining a > method might just mean the subclass doesn't support some optional behavior > defined by the base) > > -- > Richard Damon > > -- > https://mail.python.org/mailman/listinfo/python-list > -- https://mail.python.org/mailman/listinfo/python-list