10.9 Duck Typing and Polymorphism

  • Most object-oriented programming languages require inheritance-based “is a” relationships to achieve polymorphic behavior
  • Python also supports duck typing, which the Python documentation describes as:

    A programming style which does not look at an object’s type to determine if it has the right interface; instead, the method or attribute is simply called or used (“If it looks like a duck and quacks like a duck, it must be a duck.”).

  • When processing an object at execution time, its type does not matter
  • As long as the object has the data attribute, property or method (with the appropriate parameters) you wish to access, the code will work

10.9 Duck Typing and Polymorphism (cont.)

  • Reconsider the loop at the end of Section 10.8.3
    for employee in employees:
      print(employee)
      print(f'{employee.earnings():,.2f}\n')
    
  • Works properly as long as employees contains only objects that:
    • can be displayed with print (that is, they have a string representation)
    • have an earnings method which can be called with no arguments

10.9 Duck Typing and Polymorphism (cont.)

  • All classes inherit from object directly or indirectly, so they all inherit the default methods for obtaining string representations that print can display
  • If a class has an earnings method that can be called with no arguments, we can include objects of that class in the list employees, even if the object’s class does not have an “is a” relationship with class CommissionEmployee
  • Consider class WellPaidDuck:
In [1]:
class WellPaidDuck:
    def __repr__(self):
        return 'I am a well-paid duck'
    def earnings(self):
        return Decimal('1_000_000.00')
  • Clearly not meant to be employees
  • But, will work with the preceding loop
In [2]:
from decimal import Decimal
In [3]:
from commissionemployee import CommissionEmployee
In [4]:
from salariedcommissionemployee import SalariedCommissionEmployee
In [5]:
c = CommissionEmployee('Sue', 'Jones', '333-33-3333',
                       Decimal('10000.00'), Decimal('0.06'))
In [6]:
s = SalariedCommissionEmployee('Bob', 'Lewis', '444-44-4444',
    Decimal('5000.00'), Decimal('0.04'), Decimal('300.00'))
In [7]:
d = WellPaidDuck()
In [8]:
employees = [c, s, d]
  • Use duck typing to polymorphically process all three objects in the list
In [9]:
for employee in employees:
    print(employee)
    print(f'{employee.earnings():,.2f}\n')
CommissionEmployee: Sue Jones
social security number: 333-33-3333
gross sales: 10000.00
commission rate: 0.06
600.00

SalariedCommissionEmployee: Bob Lewis
social security number: 444-44-4444
gross sales: 5000.00
commission rate: 0.04
base salary: 300.00
500.00

I am a well-paid duck
1,000,000.00


©1992–2020 by Pearson Education, Inc. All Rights Reserved. This content is based on Chapter 5 of the book Intro to Python for Computer Science and Data Science: Learning to Program with AI, Big Data and the Cloud.

DISCLAIMER: The authors and publisher of this book have used their best efforts in preparing the book. These efforts include the development, research, and testing of the theories and programs to determine their effectiveness. The authors and publisher make no warranty of any kind, expressed or implied, with regard to these programs or to the documentation contained in these books. The authors and publisher shall not be liable in any event for incidental or consequential damages in connection with, or arising out of, the furnishing, performance, or use of these programs.