Compare: ############################################### class Dog(object): pass class Cat(object): pass class Cow(object): pass
def sayHi(animal): if isinstance(animal, Dog): print("Woof") elif isinstance(animal, Cat): print("Meow") elif isinstance(animal, Cow): print("Moo") else: raise ValueError("animal doesn't know how to greet") sayHi(Dog()) sayHi(Cat()) sayHi(Cow()) ############################################### where there are explicit type tests. The decision-making here, the flow of control, is explicit in the structure of the sayHi() function. Now compare that versus the following: ############################################### class Dog(object): def getGreeting(self): return "Woof" class Cat(object): def getGreeting(self): return "Meow" class Cow(object): def getGreeting(self): return "Moo" def sayHi(animal): print(animal.getGreeting()) sayHi(Dog()) sayHi(Cat()) sayHi(Cow()) ############################################### You should see similar behavior. But the control flow here is more implicit: it's not all apparent from the structure of sayHi(): sayHi() looks like straight-line code. The decision-making hides in the type of the animal. The flow of control jumps from sayHi() to the getGreeting() of the particular animal, and then finally back to sayHi() to do the printing of the greeting. One of the values of this latter approach is that it's easier to add more animals without having to rewrite sayHi(). For example, we can introduce a Crow: ################################ class Crow(object): def getGreeting(self): return "Kaaa" sayHi(Crow()) ################################ and sayHi() can deal with it just fine. In the first approach with the explicit type tests, we'd have to modify sayHi() to let it handle Crows. _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor