Have you heard this before? “Everything is an object in Python.” While many articles on the Python programming language touch on this reality, few explain what it means.
In this article, we’ll take a deep dive into objects in Python. We’ll talk about classes and how they relate to objects, and we’ll clarify whether everything is indeed an object in Python.
What is a Python Object?
A Python object is a complex data type. Not only does it act as a container for different types of data, but it also defines the attributes and methods associated with that data. While an attribute is a property of an object (i.e., the imaginary part of a complex number), a method is a function that does something with the object (for instance, computing a list’s length).
We’ll use the dir() function to determine an object’s attributes and methods:
We started by assigning the integer value 5 to our variable my_int. Seeking to determine how many attributes and methods are associated with this data type, we printed the length of dir(my_int)’s output. There were 70! This is quite a lot for a seemingly simple object such as an integer.
Next, we’ll print dir(my_int)’s first five results:
These are all names of internal methods that we may use with the object. Let’s try the __add__ method:
We typically wouldn’t add integers in Python in this manner. We’d instead use + operator, which is much more readable:
However, internally this variant resolves to the first one. Methods with double underscores (called “dunders” in Python jargon) go by the name “dunder methods” or “magic methods.”
Let’s try our dir() function on a completely different type of data: a library.
We imported the Natural Language Toolkit (NLTK) library and again printed its first five attributes. In this case, dir() returned the various modules contained in the NLTK library.
Although we might think of integers and libraries as conceptually very different (one is a basic data type, whereas the other is a collection of classes and functions), Python uses an abstraction to treat them both as objects. If you want to learn more about why Guido van Rossum (the Python language’s creator) decided to implement it that way, read his blog post here.
Common Object Methods
We saw that different objects have different attributes and methods. However, there are three methods that work with every object in Python. They provide basic information about the object, such as its location and type. Let’s briefly look at each one.
We already learned about dir(). Short for “directory,” it lists an object’s properties and functionalities in alphabetical order.
True to its name, type() returns the type of an object. Whenever you can’t remember your object’s data type, just use this handy little function:
You may also use type() to check if two objects are of the same type:
However, if you wanted to check whether an object is of a certain data type, you’d use isinstance() instead:
id() returns an object’s in-memory address. Among other things, we may use it to compare two variables and see if they reference the same object.
We used the equality operator == to find out if the addresses of our two variables were the same. Since my_int and nltk are two separate objects, we received a negative answer.
Is Everything Really an Object?
Now that we’ve taken a detailed look at Python objects, we’re now able to dig into the assertion that “everything is an object.” What’s really meant by it is that Python stores all data in objects, and consequently, that all expressions resolve to objects:
The Python language’s syntactic elements, such as statements and other keywords, are not objects. Some examples of keywords are if, def and the + operator.
When we try to use our common functions with these elements, we get an error:
To really understand the implications of treating everything as an object, we can look at languages that handle data differently. Java for instance has primitive and non-primitive data types. Only the latter (e.g., arrays and classes) are objects with associated methods. Primitive data types such as numbers and characters don’t have that functionality.
What is a Python Class?
You might’ve been finding the discussion up to now a bit abstract, so we’ll now talk about what objects look like in practice. To this end, we’ll need to talk about Python classes. Classes act as blueprints for objects; they outline the attributes and methods of each data type. When we create a new object of a built-in data type, we call an instance of that class. This process is also called instantiation.
So in the case of the integer variable my_int that we created above, we actually instantiated an object of the int class. Since the class defines attributes and methods associated with a numerical object, these are part of our new variable by default.
How to Define a Python Class
While Python has numerous classes built-in (such as integers, strings, lists, etc.), you may also define your own. In fact, in an object-oriented language, working with classes is the correct, “Pythonic” way of doing things. But if you’ve never worked with object-oriented programming, you might at first prefer the functional paradigm. However, classes are the better choice for writing modular and reusable code.
To define our own custom class, we’d use the keyword class. We’d then go on to define our class’s behavior entirely from scratch. Say we want to create a class to bake a cake. We’d name it Cake (according to Pythonic style, class names use PascalCase):
There’s a lot to unpack here! First, it looks like we included a magic method in our class. This __init__ method is called the constructor. It’s a special function that doesn’t have to be called explicitly but runs whenever we create a new class instance. We instantiate a class by calling it as we would a function, with two brackets:
Once we created our class instance, we implicitly invoked the constructor. In this example, what the constructor did was to assign an attribute to the object, namely the flavor of the cake. We can now observe it using the usual syntax:
Chocolate flavor has become a property of our object! What if we want strawberry cake instead? Easy:
Next, let’s call the class method bake() — which we defined earlier. If you look closely, you’ll see that the first argument of bake() is called self. This simply means that it’s part of the class in which we defined it. We call it with the same syntax we saw before with the __add__ method. The variable name replaces self and is implicitly passed on as the first argument:
And voilà! We baked two different objects from the same class.
With this tutorial on classes and objects, we introduced you to one of the skill sets you’ll need to work on high-stakes Python projects.
To continue your Python journey, check out our Intro to Programming Nanodegree, a program that could very well unlock career opportunities in Web and App Development, Machine Learning, Data Science, AI, and other exciting fields.