What is duck typing in Python?

There are different philosophies to data types in Python.
Register or Login to like

Python follows the EAFP (Easier to Ask Forgiveness than Permission) rather than the LBYL (Look Before You Leap) philosophy. The Python philosophy of EAFP is somewhat linked to its "duck typing" style of coding.

When a programmer creates data in code, whether it's a constant or a variable, some programming languages need to know what "type" of data it is. For example, if you set a variable to 13, a computer doesn't know whether you mean for it to be used as a word ("thirteen") or as an integer (as in 13+12=25 or 13-1=12). This is why many  languages require programmers to declare data before it's used.

For example, in this C++ code, the mynumber variable is an integer type and the myword variable is a string:

#include <iostream>
#include <string>

using namespace std;

int mynumber = 13;
string myword = "13";

int main() {
  std::cout << 13+2 << endl;
  std::cout << "My favourite number is " + myword << endl;
}

Python is clever, though, and it uses the "duck test": if a variable walks like a duck and talks like a duck, then it is a duck. In other words, Applied to computer science, that means Python examines data to determine its type. Python knows that integers are used for math and words are used in communication, so the programmer doesn't have to explain to Python how to use the data it finds in variables. Python uses duck typing to figure it out on its own, and does not attempt to do math on strings or print the contents of arrays (without iteration), and so on.

However, before we discuss these concepts, let's go over the basics:

An analogy to understand the concept of "type"

The concept of "typing" in the context of a programming language is often discussed, but often, the deeper meaning eludes us. So, let me try to explain the concept using an analogy.

In a computer program, objects and other items are stored in memory, and they are generally referred to by some "variable name." So, when you create an object of a particular class (in any of the popular programming languages), you are basically reserving a portion of memory for that object to occupy, and then you refer to this object with that variable name.

So, as an analogy, you can think of this space in memory as a kind of container or box. For this exercise, let's call it a box. So now we have two things with us—an object and a box which contains it.

To take the argument further, typically, a box must be "designed" to be able to hold the object that it contains (i.e., a box meant for holding matches won't be ideal for holding shoes, or vice versa, even though it's physically possible). So, we can agree that the object and the box which contains it must both be of a similar type? 

This, in fact, is the so-called "static typing." Basically, it means that not only the object must have a "type," but the variable name (a.k.a. the box) must have one as well, and it should be the same or similar. (I will explain why I say "similar" in a moment). This is why, in statically typed languages like Java/ C++, you need to define the type of the variable when you create it. In fact, you can create a variable name analogous to a box, even without creating any object to put in it. You can't do this in Python.

However, a dynamically typed language like Python works differently. Here you can think of the variable name, not like a box but rather analogous to a "tag" (somewhat like a price tag in a store). So, the tag does not have a type. Rather, if you ask the tag what its type is, it would probably pick the object it is tagged to at that moment. Why I say "at that moment" is because, just like in the real world, a tag attached to a shoe could also be attached to some other item at a different time. So the Python interpreter does not assign any type to a variable name, per se. But if you ask a variable name its type, then it will give you the type of the object it is currently tied to. This is dynamic typing.

This dynamic vs. static typing has a direct impact on the way you write code. Just like in the real world where you can't put shoes in a box meant for matches, so it also goes in statically typed languages—you generally cannot put objects of one type in a variable name created for objects of another type.

Strongly typed vs. weakly typed languages

There is another important concept to address here, namely, strongly and weakly typed languages. The "strength" of typing has virtually nothing to do with whether it is dynamically or statically typed. It has more to do with "casting" or the ability to convert one type of object to another. Contrary to popular perception, Python is a rather strongly typed language, just like C++ or Java. So in Python, for example, you can't add, say, an "integer" to a "string," however, you can do this in a language like JavaScript. JavaScript, in fact, is one of the notoriously "weakly typed" languages. So, it should be clear that strong/weak typing is an altogether different scale than static/dynamic typing. In general, scripted languages like Python tend to be dynamically typed, while compiled languages tend to be statically typed.

Duck typing and EAFP and LBYL

Python follows the duck typing style of coding.

Let's again take a real-world example. Suppose you have an object "Machine M." Now, you don't know whether this Machine M has the capability to fly or not. The way LBYL would proceed vs. EAFP is illustrated in the figure below:

LBYL vs EAFP

Let's clarify the concept with some Python code (with fictitious functions):

# LBYL:- Look Before You Leap
if can_fly():
    fly()
else:
    do_something_else()
   
# EAFP:- Easier to Ask Forgiveness than permission
try:
    fly()
except:
    clean_up()  

How duck typing supports EAFP

Duck typing is ideal for the EAFP style of coding. This is because we don't care about the "type" of an object; we care only about its "behavior" and "capability." By "behavior," I basically mean its attributes, and by "capability," I mean its methods.

To sum up:

If you see a lot of if-else blocks, then you are an LBYL coder.

But if you see a lot of try-except blocks, you are probably an EAFP coder.

What to read next
Tags
User profile image.
Anurag Gupta is an Engineer by education but a police officer by profession. He is a Python enthusiast who has recently co-authored a book on Python named Python Programming: Problem Solving, Packages and Libraries published by McGraw Hill. He is available at 999.anuraggupta at Gmail and loves to hear from readers on Python related subjects.

9 Comments

This is interesting Anurag, my first programming language was Pascal and the good coding habits that it forced me into have stuck over time. However, somebody later remarked to me that this was actually a weakness for a teaching language as it gave students no choice, rather than letting them see why those good programming habits were preferable to the alternatives. This is a valid argument but I am still grateful for that initial touch of discipline.

Tbh, if you see a lot of if/then/else or a lot of try/catch, it probably means you are poor programmer.

What a well-written article! Thank you Anurag. Following Peter Cheer's comment above, I think it would be super if you followed up with another article about "common errors enabled by duck typing and how to avoid them".

I've been programming in Python for just shy of 20 years, and the main thing I've noticed is that EAFP makes it very easy to wind up with very cryptic error messages if you're not careful.

urwid (The TUI framework for Python) suffers heavily from that.

(If you don't feed it what it expects when building your widget tree, you'll get a horrendously cryptic error about missing attributes/methods somewhere deep within urwid.)

Well that explains to me the basic idea of “duck typing”. It also, makes clear to me why folks that learn by analogy never seem to understand what is going on with the actual machine they’re programming or the problems they’re having with the operating system. I’ve met a few developers now, that can’t understand outside of the silly analogies they were taught with. Now, they have to go learn some of the reality if computers.

IMHO, there are 3 ways to deal with a difficult concept (1) Skip it (2) Give an anology and (3) Go deep into its internals.
Now depending upon the readers you are addressing, all 3 are good.
I gave the anology of a "variable name" as a "box" in certain languages (Like C++) and as a "tag" in others (Like Python) to give the readers a deeper understanding into the concept without discussing the deeper details. The internet is full of articles on "duck typing" and you could find any amount of details. But the challenge before us, as we try to write on such subjects, is to give an "insight" into the concept in as simple a way as possible.
As one of my teachers said once "If your student cannot understand a concept, try to guess whether the fault is in his learning or your teaching"

Nice comments, Anurag Gupta. In a language like Python we are quite some distance away from the machine that is executing the code "down below", and in any case typing is much less about the machine and much more about our interpretation of the results.

In reply to by Anurag Gupta (not verified)

Creative Commons LicenseThis work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.