Python makes everything an object

In python everything is an object. This means that every object in python has the ability to be assigned to a variable or that every object has the ability to be passed to a function as an argument. Python makes objects out of the usual suspects; strings, ints, lists, tuples etc… But it also makes things like modules, classes and functions into objects as well. An object in python is essentially an instance of a data structure that has what are called data members, like variables and methods (methods are just functions defined in a class). To better understand python objects it is important to understand a few different concepts in python. The concept of type in python and the concept of the object id# are very important as is the difference between mutable and immutable types. Lets begin by going over some examples of using the type() and id() functions in python and move on to a discussion mutable or immutable types.

Python: Id() and type()

In python the id() function can be used to return the “identity” of any object. The id generated is a long integer that is unique to every object in the program. The id number that pythons id() returns is the location in memory where that object is located. You can think of the id number as the address to a house, each address is unique and leads to only one house. If two addresses led to more than one house than the mailman would get very confused. For python, each id# is the address of the object. This helps to keep all the objects distinct and keeps them from getting confounded by the user or the computer. To see id() in action just look at this python interpreter session to better understand:

>>> a = 1
>>> b = a
>>> c = b
>>> d = 1
>>> id(a) #id(a) returns the memory address of a
14267265829739
>>> id(b) #id(b) returns the same address as id(a)
14267265829739
>>> id(c) #id(c) returns the same address as id(a)
14267265829739
>>> id(d) #id(d) returns the same address as id(a)
14267265829739

Eagle eye readers will have noticed that all the variables have the same address. What doest that mean? It means that all of these variables are sharing the same address or better yet they are pointing to the same object. Or, said another way, they are all pointing at the same value located at the same location in the computer memory. In python it is often the case that multiple variables can point to the same memory location. This allows the python program to use less memory because one value can be shared and pointed to by multiple variables. The id function is useful in determining if two different variables are sharing the same value.

So every object in python gets its own address regardless of what type of object it may be. While knowing an objects id we can determine where it is in computer memory as well as if two variables may point to the same value in memory. But that does not tell us what the object is. To do this we use the type() function. The type() returns the type of any object just by passing that object as an argument. Check out this python interpreter session to get a better idea of what type can do:

>>> type(1)
<class 'int'> # type(1) returns int
>>> type({"key":"value"})
<class 'dict'> # type({"key":"value"}) returns dict
>>> type([1, 2, 3])
<class 'list'> # type([1, 2, 3]) returns list
>>> type((1, 2))
<class 'tuple'> # type((1, 2)) returns tuple
>>> type("String")
<class 'str'> # type("String") returns string

This does not represent the list of all “types” in python but since everything in python is an object, everything has a type and using the type() function is the best way to quickly ascertain the type of any object you are dealing with.

Mutable Objects in Python

While everything in python is an object python does not handle all the objects in the same way. Some objects are mutable which means that their meaning or value can be altered or changed by the program or the user. Immutable objects in python have values or meanings that cannot be changed. If the value of an immutable object has been altered or updated a completely new object gets returned that has a different id number associated with it. Essentially, it is a completely new object instance located in a different place in memory. Lets look at a list of mutable and immutable types in python.

A list of mutable and immutable types in python:

Immutable Python Types:
int
float
decimal
complex # These types are immutable and cannot be
bool # changed. To change or update an immutable
string # you must make a new instance at a new address
tuple
range
frozenset
bytes
Mutable Python Types:
list
dict # These types are mutable and can be changed
set # while retaining the same id or address
bytearray
user-defined classes (unless specifically made immutable)

Understanding mutability in python can be very useful when writing code that is efficient and easy to understand. For an example lets look at an immutable type like a string.

>>> string = 'Python'
>>> Python[0] = 'p'
>>> TypeError: 'str' object does not support item assignment

Trying to change the string “Python” to the string “python” we can see the interpreter brings up a TypeError message indicating that we cannot change the string in memory i.e. the string does not support having values in it reassigned to other values. To obtain the string “python” we would need to create a new string with a new id number in a new place in computer memory. Lets look at another example of immutability and mutability in python.

Lets compare a mutable list type and an immutable tuple type and see how they behave differently.

>>> list = [2,4]
>>> tuple = (2, 4)
>>> list[0] = 9 # reassigning the first value of list
>>> print(list)
[9, 4]
>>> tuple[0] = 9 # reassigning the first value of a tuple
TypeError: 'tuple' object does not support item assignment

With the mutable list named “list” we were able to reassign the first element to be 9. But when we tried to change the first element of the tuple we ran into the TypeError message again telling us that the immutable tuple type cannot be redefined. the tuple is immutable and does not support this operation. Lets look how mutability can affect what happens when you choose data types to work with in python.

In the example below we are concatenating a string with with different elements contained in some data structure or container. The string is named “string” and starts out empty.

string = ""
for elements in container:
string = string + str(elements)

For every loop in this for loop a string gets concatenated with another element from the container. And for every time there is a concatenation a new string is created and the old string is abandoned. If a container carries a lot of strings to concatenate we will end up creating and storing many different strings throughout the process of the for loop iterating. Once the for loop is finished, all of the intermediate strings will be discarded and the overall process is waist full and costly with computer memory. To do this in a way that does not soak up computer memory and resources we need to use a different approach i.e a different data type that is mutable like the example below.

string = []
for elements in container:
string.append(str(elements))

This approach is much efficient because it uses a list (a mutable type) instead of the immutable string type. Here the list is appended with the new string at every iteration of the loop. Since the list type is mutable it retains its id number and location in computer memory even while the new strings are being appended to it. This means that intermediate strings with different addresses are not created at every loop like in the first example.

Here is another example that illustrates the importance of mutable and immutable objects in python.

>>> def function(list=[])
list.append("String")
return list
>>> function()
>>> function()
>>> print(list)
["StringString"]

In this example we pass the function a list that we named “list”. Because the type list is a mutable type it can be changed without making a new list in a new memory location. So the result of this loop is that for every iteration of the loop the “string” is appended to the list. The list remains in the same memory location and “string” is appended to the SAME list at each iteration. you might think that since the function is passed an empty list as an argument that it would create a new list for every iteration but now that you know about mutable types it makes more sense that strings are appended to the same list for every iteration in the for loop.

Show your support

Clapping shows how much you appreciated Chris Turner’s story.