Launching Python3 propels you into a world that consists of objects, links among said objects, and methods that operate on them. The goal is to leave you better equipped to understand Python’s paradigm so you can comprehend its language.
In the object-oriented paradigm, a class is the blueprint containing attributes and methods it controls. An object is an instance of a class much like a house is an instance of the base blueprint. Attributes and methods that were defined in the base class are available in any instance of the class. Strings, floats, ints, and lists are all valid examples of classes in the language. Initializing a variable and binding it to a specific value is referred to as instantiation, meaning that an object belonging to a specific class was created. Based on the example below, the left hand side of a “variable assignment” is the variable name and the right hand side is a specific object created in memory. That name is bound to the object in memory containing the value 1. In a language like C, a variable is like a “box” containing the value that was assigned and therein lies the difference with Python. Values created in the Python space are objects belonging to specific classes and variables are simply references to these objects. Code consists of object manipulation and this philosophy permeates through every aspect of the language.
>>> # Example of instantiating an int object
>>> a = 1
<class 'int'>>>> string1 = "Hemant"
<class 'str'>>>> # Demonstrating the use of a string method on the object "Hemant"
The builtin function, type(), returns the class that the object belongs to.
Given that Python deals with values as objects, it’s helpful to understand how it works in a toy problem.
>>> a = 1
>>> b = 1
The code above has 2 variable names that refer to the same value. In C, these variables would store the same value in different memory locations on the stack. However, remember that variable names are just tags that reference an object in memory. The point of this discussion is that a and b ultimately point to the same object ‘1’ in memory!
>>> a is b
>>> a == b
Using the ‘is’ and ‘==’ operators on the variable names returns True in both instances. The former operator checks for whether the names refer to the same object. Variables in Python are names that reference objects created in memory. The latter operator tests for object value equality, which returns True because a and b point to the same value. The return value from the is operator can be substantiated using the id() function. This function returns a unique integer representing the memory address of the underlying object.
The return value from id() is the same, meaning that a and b refer to the same object.
Objects can come in two flavors: Mutable and Immutable. On a basic level, the difference lies in the ability to be transformed. Mutable objects can be changed whereas immutable objects are frozen after instantiation. Take for example the list, modifying the list’s elements or the size of the list is permissible by the interpreter. Initializing the list with specific values and changing the list elements at a later time won’t cause any exceptions to be raised by the interpreter.
>>> my_list = [1, 2, 3]
>>> my_list = 5
[1, 2, 5]
Objects of this kind are not capable of being changed. At the time of instantiation, values that were placed in the object are frozen. Instantiating a generic string and subsequently attempting to modify the string is not possible with objects of this type.
>>> string1 = "Hemant"
>>> string1 = 'c'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
>>> # This same traceback is seen when attempting to assign value in an immutable object like a tuple
Why does it matter and how does Python treat mutable vs immutable objects?
Mutability is significant because multiple names can be bound to specific objects in memory. Depending on the specific situation, having a mutable type would also affect all its references which can lead to issues. For example, strings couldn’t be used as keys in dictionaries if they were mutable. Immutable types give you the guarantee that modifications to the underlying object are not permissible.
How are arguments passed to functions and what does that imply for the mutability of objects?
Python functions are Call-By-Object-Reference, meaning the mutability of the object affects the function’s behavior. Types that are immutable are passed by value and don’t make any changes to the underlying object. Mutable objects are passed by reference so the modification of the underlying object is possible.
Python’s object oriented paradigm is interesting because it exhibits behavior that is inherently different compared to C. Variable names link to objects in memory so it’s possible to have multiple references to the same object. Mutability affects the behavior of the movement of data to and from functions.