Introduction
In this lab, we'll cover the basics of Python assignment and reference. We'll explore how Python handles assignments, how to create references, and how to work with mutable and immutable objects.
In this lab, we'll cover the basics of Python assignment and reference. We'll explore how Python handles assignments, how to create references, and how to work with mutable and immutable objects.
In Python, assignment is the process of binding a name to an object. Assignment statements have the following general form:
variable = expression
The expression on the right-hand side is evaluated, and its value is assigned to the variable on the left-hand side.
Let's look at a simple example:
Open the Terminal and typing the following command in the terminal.
python3
Then, enter the following code.
## Assign the value 42 to the variable 'x' and print it.
x = 42
print(x)
Output:
42
Here, we assign the x
to the variable 42
using the operator =
. Then, we print the values of x
.
In Python, variables are references to objects. When you assign a value to a variable, you're actually creating a reference to the object that represents the value.
Here's an example to illustrate this concept:
## Illustrate Python references.
x = [1, 2, 3]
y = x
y.append(4)
print("x:", x)
print("y:", y)
Output:
x: [1, 2, 3, 4]
y: [1, 2, 3, 4]
In this example, both x
and y
refer to the same list object. When we modify the list through the y
reference by appending 4
, the change is reflected in both x
and y
.
Python has two types of objects: mutable and immutable.
Mutable objects can be modified after they are created. Lists, dictionaries, and sets are examples of mutable objects.
Immutable objects cannot be modified once they are created. Integers, floats, strings, and tuples are examples of immutable objects.
Let's look at an example that demonstrates the difference between mutable and immutable objects:
## Mutable object example
mutable_list = [1, 2, 3]
another_mutable_list = mutable_list
another_mutable_list.append(4)
print("mutable_list:", mutable_list)
Output:
mutable_list: [1, 2, 3, 4]
mutable_list
append a 4
to the end of the list because it's mutable objects, but immutable objects cannot be modified once they are created.
## Immutable object example
immutable_string = "hello"
another_immutable_string = immutable_string
another_immutable_string = another_immutable_string.upper()
print("immutable_string:", immutable_string)
Output:
immutable_string: hello
It doesn't have any change, and if we want to change the immutable_string
as follows, Python shell will throws a TypeError:
immutable_string[0] = '1'
Output:
TypeError: 'str' object does not support item assignment
Let's see a few more examples to reinforce the concepts we've learned:
Avoid using mutable objects as default arguments in functions:
def bad_append(new_item, a_list=[]):
a_list.append(new_item)
return a_list
print(bad_append('one'))
Output:
['one']
It looks good, but if we call this function again:
print(bad_append('two'))
Output:
['one', 'two']
The problem here, is that the default value of a_list
is evaluated at function definition time. So every time you call the function, you get the same default value.The correct way is to create it at run time instead, inside the function.
def append_to_list(item: int, a_list: list = None) -> list:
"""Append an item to a list and return the updated list."""
if a_list is None:
a_list = []
a_list.append(item)
return a_list
list_a = append_to_list(1, [1, 2, 3])
print(list_a)
Output:
[1, 2, 3, 1]
Use the copy
module to create a new object when you want to work with a copy of a mutable object:
import copy
## Demonstrate the use of the copy module.
original_list = [1, 2, 3]
copied_list = copy.copy(original_list)
copied_list.append(4)
print("original_list:", original_list)
print("copied_list:", copied_list)
Output:
original_list: [1, 2, 3]
copied_list: [1, 2, 3, 4]
In this example, copied_list
is a new object that is a copy of original_list
. When we append 4
to copied_list
, original_list
remains unchanged.
For nested mutable objects, using the copy
function doesn't work:
## your copy example here
original_nested_list = [[1, 2], [3, 4]]
copied_nested_list = copy.copy(original_nested_list)
copied_nested_list[0].append(5)
print("original_nested_list:", original_nested_list)
print("copied_nested_list:", copied_nested_list)
Output:
original_nested_list: [[1, 2, 5], [3, 4]]
copied_nested_list: [[1, 2, 5], [3, 4]]
We can see that when we append 5
to copied_nested_list
, the original_nested_list
also appends 5
. So you should use the deepcopy
function instead.:
## your deepcopy example here
original_nested_list = [[1, 2], [3, 4]]
deep_copied_list = copy.deepcopy(original_nested_list)
deep_copied_list[0].append(5)
print("original_nested_list:", original_nested_list)
print("deep_copied_list:", deep_copied_list)
Output:
original_nested_list: [[1, 2], [3, 4]]
deep_copied_list: [[1, 2, 5], [3, 4]]
In this example, deepcopy
function copies the original_nested_list
recursively, while the copy
function creates a reference object to the first-level data of the original_nested_list
.
In this Python programming tutorial, we covered the basics of Python assignment and reference. We explored how Python handles assignments, how to create references, and how to work with mutable and immutable objects. By understanding these concepts, you'll be better equipped to write efficient and correct Python code.