Python3: Mutable, Immutable… everything is object!

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.
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 “Testing”.
>>> var_1 = “Testing”
>>> id(var)
139733739890736
And var_2 is the same
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 (“Testing”).
They both have the same value and the same object verifaible with == and is
List have the same value but not the same object.
To understand better how objects work in Python, we would need to understand id and type functions.
Tyoe return the type of an object
>>> type(var_1)
<clas 'str'>
Mutable objects in Pythons are lists, dictionaries, set, byte array. Mutable means that you can change object’s content without changing it’s identity.
If we want to add values to our string, we can just add (+) another string to the existing one by: string += “new values”
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.