Python3: Mutable, Immutable… everything is object!
Everything（all values) in Python is an object or a class. What does it mean exactly? Everything is an object in the sense that it can be assigned to a variable or passed as an argument to a function. Almost everything has attributes and methods.
For example an integer in Python is an object, a large block of “structured” memory, typically over 100 bits long, and different parts of that structure are used internally to the interpreter.
Objects and Values
An object in Python is something you can refer to. Let’s assign some values to a variable. Which essentially means we make var_1 refer to object “Holberton”.
And same values to another variable:
As we can see both var_1 and var_2 have same identity. That means they both refer to the same values (objects) and no other space was allocated for the new string with identical values. It is safe to do in Python, since strings are immutable, so it is the way to optimize resources by referring two strings that refer to the same string to the same object (“Holberton”).
Let’s check if both vars have the same value:
And if they both refer to the same object:
Both list_1 and list_2 have same values.
But they don’t refer to the same object.:
To understand better how objects work in Python, we would need to understand id and type functions.
The id() function in Python returns identity of the object. This is an integer which is unique for the given object and remains constant during its lifetime.
Syntax: id(object) — id of the object will be returned.
The type() function returns type of the object.
Syntax: type(object) — type of the object will be returned.
3. Mutable objects in Pythons are lists, dictionaries, set, byte array. Mutable means that you can change object’s content without changing it’s identity.
Objects like strings, integers, floats, tuples, frozen set, bytes, complex can not be changed. (exception: tuples and frozen sets [because they are containers and can contain mutable objects like lists for example])
Example of immutable objects:
- Creating a string that refers to values “Holberton”:
2. Trying to change values of position one of the string:
As we can see assignment to the position  is not possible. We can not change the values that string refers to.
If we want to add values to our string, we can just add (+) another string to the existing one by: string += “new values”
Now let’s check the id of the new string:
It changed! Which means that no new values were added to the original string, but a new string was created, which of course has it’s own identity.
Mutability and immutability are both are very important. If you need to create a large string, it would be very inefficient to keep concatenating all newly created strings. In that case you would want to use list comprehension, which is a mutable type. On the other hand, immutability is very important when you want to make sure your original will never be changed.
An integer object in Python
To avoid allocating a new integer object each time a new integer object is needed, Python allocates a block of free unused integer objects in advance. PyIntObjects structure is used by Python. The array of 262 integer objects is initialized. They don’t have any values assigned to them — they are free integers that are ready to be called and used whenever needed. It speeds up the process, because you don’t need to create a new object when you need to use an integer, the value will simply be assigned to the next available object and no memory allocation will be necessary.
The value range of these integer objects is -5 to 257 — because they are the most used integers and they are defined like that:
#define NSMALLPOSINTS 257
#define NSMALLNEGINTS 5
When you assign a value to a variable (variable passed to a function by assignment) it will check if the integer is in range of -5 to 257 and return the integer object pointed by the small integers at the offset.
Names and Objects
Objects have individuality, and multiple names (in multiple scopes) can be bound to the same object. This is known as aliasing in other languages. This is usually not appreciated on a first glance at Python, and can be safely ignored when dealing with immutable basic types (numbers, strings, tuples). However, aliasing has a possibly surprising effect on the semantics of Python code involving mutable objects such as lists, dictionaries, and most other types. This is usually used to the benefit of the program, since aliases behave like pointers in some respects. For example, passing an object is cheap since only a pointer is passed by the implementation; and if a function modifies an object passed as an argument, the caller will see the change — this eliminates the need for two different argument passing mechanisms. (source)