Python3: Mutable, Immutable… everything is an object!
In Python3, everything is an object. This includes primitive data types like integers and strings and more complex data structures like lists and dictionaries. Each object has an identity (its memory address), a type (which defines its behaviour), and a value.
x = 42
print(id(x)) # prints the memory address of x
print(type(x)) # prints <class 'int'>Objects in Python can be either mutable or immutable. Mutable objects can change their value after creation, while immutable objects cannot. Some common examples of mutable objects include lists and dictionaries, while common examples of immutable objects include integers, strings, and tuples.
my_list = [1, 2, 3]
my_list[0] = 42 # this is allowed because lists are mutable
my_string = "hello"
my_string[0] = "H" # this raises an error because strings are immutableThe distinction between mutable and immutable objects matters because it affects how Python treats them in various situations. For example, when passing arguments to functions, mutable objects are passed by reference, while immutable objects are passed by value. This means that changes made to a mutable object within a function will also be reflected outside the function.
def my_function(my_list):
my_list.append(4)
my_list = [1, 2, 3]
my_function(my_list)
print(my_list) # prints [1, 2, 3, 4] because the list was modified within the function
def my_function(my_string):
my_string += " world"
my_string = "hello"
my_function(my_string)
print(my_string) # prints "hello" because strings are immutable and cannot be modified within the functionIn addition to the basic concepts covered above, this project also includes advanced tasks that explore more complex topics related to mutability in Python. One such task involves writing a function magic_string() that returns the string “BestSchool” n times the number of iterations.
def magic_string():
magic_string.counter += 1
return ", ".join(["BestSchool"] * magic_string.counter)
magic_string.counter = 0
for i in range(10):
print(magic_string())Understanding Python's mutability is essential for writing efficient and effective code. By knowing how Python treats different types of objects in different situations
In Python, an assignment creates a new reference to an object, while referencing simply refers to an existing object. This distinction is important because it affects how changes to things are reflected in different parts of your code.
For example, when you assign a new value to a variable referencing a mutable object, the original object is not changed. Instead, a new object is created, and the variable now references this new object. Here's an example that demonstrates this:
my_list = [1, 2, 3]
new_list = my_list
new_list = [4, 5, 6]
print(my_list) # prints [1, 2, 3] because the original list was not changed
print(new_list) # prints [4, 5, 6] because a new list was created and assigned to newIn Python, when you create an immutable object, such as an integer or a string, it is stored in memory and given a unique memory address. This memory address is returned by the id function and can be used to identify the object.
Since immutable objects cannot change their value after being created, Python can optimize their storage by reusing existing objects with the same value. For example, creating two integer objects with the same value may reference the same object in memory. Here's an example that demonstrates this:
x = 42
y = 42
print(id(x)) # prints the memory address of x
print(id(y)) # prints the same memory address as x because both variables reference the same objectThis optimization can save memory and improve performance when working with many immutable objects.
In Python, when you create an immutable object, such as an integer or a string, it is stored in memory and given a unique memory address. This memory address is returned by the `id` function and can be used to identify the object. Since immutable objects cannot change their value after being created, Python can optimize their storage by reusing existing objects with the same value. For example, creating two integer objects with the same value may reference the same object in memory. Here’s an example that demonstrates this: ```python x = 42 y = 42 print(id(x)) # prints the memory address of x print(id(y)) # prints the same memory address as x because both variables reference the same object ``` This optimization can save memory and improve performance when working with large numbers of immutable objects.
Get Emmanuel Nyadongo’s stories in your inbox
Join Medium for free to get updates from this writer.
For example, when passing arguments to functions, mutable objects are passed by reference, while immutable objects are passed by value. This means that changes made to a mutable object within a function will be reflected outside the function as well.
In Python, when you pass an argument to a function, the value of the argument is assigned to a local variable within the function. If the argument is an immutable object like an integer or a string, this assignment creates a new reference to the object, and any changes made to the local variable within the function do not affect the original object.
However, if the argument is a mutable object like a list or a dictionary, this assignment simply creates a new
In CPython, small integers (from -5 to 256) are pre-allocated when the interpreter starts up. This means that these integers are created in memory and can be reused whenever they are needed in your code.
This optimization can save memory and improve performance when working with small integers because it avoids the overhead of creating new integer objects every time a small integer is needed.
Here’s an example that demonstrates this:
x = 42
y = 42
print(id(x)) # prints the memory address of x
print(id(y)) # prints the same memory address as x because both variables reference the same pre-allocated integer object
x = 1000
y = 1000
print(id(x)) # prints the memory address of x
print(id(y)) # prints a different memory address than x because these integers were not pre-allocated, and new objects were created for each variableIn CPython, small integers (from -5 to 256) are pre-allocated when the interpreter starts up. This means that these integers are created in memory and can be reused whenever they are needed in your code. This optimization can save memory and improve performance when working with small integers because it avoids the overhead of creating new integer objects every time a small integer is needed. Here's an example that demonstrates this: ```python x = 42 y = 42 print(id(x)) # prints the memory address of x print(id(y)) # prints the same memory address as x because both variables reference the same pre-allocated integer object x = 1000 y = 1000 print(id(x)) # prints the memory address of x print(id(y)) # prints a different memory address than x because these integers were not pre-allocated and new objects were created for each variable ```
In Python, an alias is created when two variables reference the same object in memory. This can happen when you assign one variable to another or pass a mutable object as an argument to a function.
Since both variables reference the same object, changes made to one variable will also be reflected in the other variable. Here's an example that demonstrates this:
my_list = [1, 2, 3]
my_alias = my_list
my_alias.append(4)
print(my_list) # prints [1, 2, 3, 4] because my_alias and my_list reference the same objectBeing aware of aliases when working with mutable objects is essential because they can lead to unexpected behaviour if you're not careful.
In Python, an alias is created when two variables reference the same object in memory. This can happen when you assign one variable to another or pass a mutable object as an argument to a function. Since both variables reference the same object, changes made to one variable will also be reflected in the other variable. An example demonstrates this: ```python my_list = [1, 2, 3] my_alias = my_list my_alias.append(4) print(my_list) # prints [1, 2, 3, 4] because my_alias and my_list reference the same object ``` It's essential to be aware of aliases when working with mutable objects because they can lead to unexpected behaviour if you're not careful.
In CPython, small integers are pre-allocated when the interpreter starts up to save memory and improve performance. The values of NSMALLPOSINTS and NSMALLNEGINTS determine the range of small integers that are pre-allocated.
NSMALLPOSINTS defines the number of positive small integers pre-allocated, while NSMALLNEGINTS establishes the number of small negative integers pre-allocated. By default, NSMALLPOSINTS is 257, and NSMALLNEGINTS is set to 5 in CPython. This means that integers from -5 to 256 are pre-allocated when the interpreter starts up.
These are implementation details of CPython (the most widely used implementation of Python) that relate to the pre-allocation of small integers. In CPython, small integers are pre-allocated when the interpreter starts up to save memory and improve performance. The range of pre-allocated small integers is determined by the values of `NSMALLPOSINTS` and `NSMALLNEGINTS`. `NSMALLPOSINTS` defines the number of positive small integers that are pre-allocated, while `NSMALLNEGINTS` describes the number of small negative integers that are pre-allocated. By default, `NSMALLPOSINTS` is 257 and `NSMALLNEGINTS` is 5 in CPython. This means that integers from -5 to 256 are pre-allocated when the interpreter starts up.
Tuples and frozen sets are both examples of immutable objects in Python. This means that their value cannot be changed after they are created. However, they can contain mutable objects like lists or dictionaries.
Since tuples and frozen sets can contain mutable objects, it's possible to indirectly change their value by modifying their mutable objects. Here's an example that demonstrates this:
my_list = [1, 2, 3]
my_tuple = (my_list,)
my_list.append(4)
print(my_tuple) # prints ([1, 2, 3, 4],) because the list within the tuple was modified
my_set = {1, 2}
my_frozenset = frozenset([my_set])
# my_set.add(3) # this raises an error because sets within a frozenset cannot be modifiedIt’s essential to be aware of this behaviour when working with tuples and frozen sets that contain mutable objects because it can lead to unexpected behaviour if you’re not careful.









