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:
A .__getitem__() method as described
in Section 26.3.16, “__getitem__(): Get one item from a
sequence or mapping”.
A .__iter__() method as described in
Section 26.3.17, “__iter__(): Create an iterator”.