Next / Previous / Contents / TCC Help System / NM Tech homepage

19.3. Duck typing, or: what is an interface?

 

When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck.

 
 --James Whitcomb Riley

The term duck typing comes from this quote. In programming terms, this means that the important thing about a value is what it can do, not its type. As the excellent Wikipedia article on duck typing says, “Simply stated: provided you can perform the job, we don't care who your parents are.”

One common example of duck typing is in the Python term “file-like object”. If you open a file for reading using the open() function, you get back a value of type file:

>>> inFile = open('input')
>>> type(inFile)
<type 'file'>

Let's suppose that you write a function called numberIt() that takes a readable file as an argument and prints the lines from a file preceded by five-digit line numbers. Here's the function and an example of its use:

>>> def numberIt(f):
...     for lineNo, line in enumerate(f):
...         print "{0:05d} {1}".format(lineNo, line.rstrip())
... 
>>> numberIt(inFile)
00000 Kant
00001 Heidegger
00002 Hume

The way you have written the numberIt() function, it works for files, but it also works for any iterable.

Thus, when you see the statement that some Python feature works with a “file-like object,” that means that the object must have an interface like that of the file type; Python doesn't care about the type, just the operations that it supports.

In practice, the enumerate() function works with any iterable, so your function will also work with any iterable:

>>> numberIt(['Kant', 'Heidegger', 'Hume'])
00000 Kant
00001 Heidegger
00002 Hume

So in Python when we say that we expect some value to have an interface, we mean that it must provide certain methods or functions, but the actual type of the value is immaterial.

More formally, when we say that a value supports the iterable interface, that value must provide either of the following features: