Everything is Object in Python

Alex Rivera Cruz
5 min readMay 29, 2021

--

You’ve probably heard that everything is an object in Python, but what does that mean?

Python is one of the most popular object-oriented languages, and it means that this language consist of objects, this objects allow us to have our own methods and attributes without having to re-create them each time.

Here is a representation of an object:

Most programming languages provide a keyword called class to create an Object, and python is not an exception to this.

What is id()?

The id() is a function that returns a unique id for the specified object. The id is assigned to the object when it is created, is “unique and constant” for the object as long as you use it.

Example:

# Declaring two string objects:>>> obj1 = "Hello"
>>> obj2 = "Alex"
# Getting their ids:>>> id(obj1)
119425024564445
>>> id(obj2)
142210142249274

What is type()?

type() method returns class type of the argument(object) passed as parameter. type() function is mostly used for debugging purposes.

The type() function has two different forms:

type(object)
type(name, bases, dict)

If a single object is passed to type(), the function returns its type:

>>> numbers_list = [1, 2, 3]
>>> print(type(numbers_list))
<class 'list'>
>>> class Lex:
a = 0
>>> lex = Lex()
>>> print(type(lex))
<class '__main__.Lex'>

If three parameters are passed to type(), it returns a new type object:

Programiz.com
>>> o1 = type('X', (object,), dict(a='Foo', b=12))>>> print(type(o1))
<class 'type'>

Mutable Objects

Mutable objects are objects whose values ​​can be changed; Examples of mutable objects are lists, dictionaries, collections, and byte arrays.

For example:

#Create a list of elements
>>> list_1 = [1, 3.3, "lex"]
>>> print(id(list_1))
142410142242274

You can change some of these items over time, but the “id” of the list will remain the same, which means that the list will be the same object when the whole program is running, unless it is removed first, of course . We will replace one element of the list

>>> list_1[0] = 2
>>> list_1
[2, 3.3, "lex"]
>>> print(id(list_1))
142410142242274

What happens if we create two lists with the same value?

>>> n = [5, 4, 8]
>>> m = [5, 4, 8]
>>> n == m
True
>>> n is m
False

It’s because they refer to different objects.

If we want that both list refer to the same object we have to apply a technique called “aliasing”

>>> n = [5, 4, 8]
>>> m = n
>>> n is m
True

Immutable objects

An immutable object is an object that cannot be changed or edited after it is created. Examples are number, string, tuple, frozen set, and bytes.

>>> string_1 = "lex"
>>> string_1[0] = "p"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment

Now, what happens if we assign the same value to two objects

>>> string_1 = "lex"
>>> string_2 = "lex"
>>> string_1 == string_2
True
>>> string_1 is string_2
True

That is because the refer to the same object, they have the same id.

>>> id(string_1), id(string_2)
(122843445625244, 122843445625244)# Both strings have the same id

Why does it matter and how differently does Python treat mutable and immutable objects

Below you can see a diagram that classifies each type in Python as mutable or immutable, and the relationship between these types and the variables assigned to them:

So, we can conclude that in mutable objects you can manipulate the value of this object to change its value, But vice versa, you cannot change the value of an immutable object.

How arguments are passed to functions and what does that imply for mutable and immutable objects

For us, it is important to understand the difference between mutable and immutable types, and how to handle them when passing them to functions. When using appropriate objects, memory efficiency will be greatly reduced. For example, if a mutable object is called by reference in a function, the original variable itself can be changed. Therefore, to avoid this situation, the original variable must be copied to another variable. Immutable objects can be called by reference, because their value cannot be changed anyway.

>>> def updateList(list1):
... list1 += [3]
>>> n = [1, 2]
>>> print(id(n))
13332154155564
>>> updateList(n)
>>> print(n)
[1, 2, 3]
>>> print(id(n))
13332154155564

As we can see from the above example, we have called the list via call by reference, so the changes are made to the original list itself.

>>> def updateNumber(n):
... print(id(n))
... n += 10
>>> b = 5
>>> print(id(b))
10055680
>>>> updateNumber(b)
10055680
>>> print(b)
5

In the above example, the same object is passed to the function, but even if the object is the same, the value of the variable will not change. This is called pass by value. So, what is going on here? When a function calls a value, only the value of the variable is passed, not the object itself. Therefore, the variable that references the object will not change, but the object itself will change, but only within the scope of the function. Therefore, the changes were not reflected.

Preallocation in Python

In Python, upon startup, Python3 keeps an array of integer objects, from -5 to 256. For example, for the int object, macros called NSMALLPOSINTS and NSMALLNEGINTS are used:

#ifndef NSMALLPOSINTS
#define NSMALLPOSINTS 257
#endif
#ifndef NSMALLNEGINTS
#define NSMALLNEGINTS 5
#endif
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
/* References to small integers are saved in this array so that they
can be shared.
The integers that are saved are those in the range
-NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive).
*/
static PyIntObject *small_ints[NSMALLNEGINTS + NSMALLPOSINTS];
#endif
#ifdef COUNT_ALLOCS
Py_ssize_t quick_int_allocs;
Py_ssize_t quick_neg_int_allocs;
#endif

What does this mean? This means that when you create an int from the range of -5 and 256, you are actually referencing to the existing object.

--

--