# Python - Mutable Data Types

Many people would think this is too easy for them, but believe me, it is a trick. The Python program allows you to create variables without declaring their type. This is great for beginners, but it also causes a lot of pain in maintenance, and the mutable type is one of them.

Let’s start with the basic immutable types Tuple and Set, we create a **Tuple** type variable called “fruit” and assign two values to it and then try to update it.

```python
>>> fruit = ("banana", "grape")
>>> fruit[0] = "orange"
```

The following error will occur because it is an immutable type. In addition, it happens in the **Set** type variable as well.

```python
>>> Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
```

So what would happen if we try to do the same thing in a **mutable** type variable like a List, we can update the value successfully.

```python
>>> names = ["Nick", "Eric"]
>>> names[0] = "Francis"
>>> names
['Francis', 'Eric']
```

In the above examples, we know **List** type variable can change the value after creation, as a result, let’s try something interesting now

```python
def update_first_value(names: List[str]) -> List[str]:
    names[0] = "Francis"
    return names


student_names = ["Nick", "Eric"]
updated_student_names = update_first_value(student_names)

print(f"original list: {student_names}")
print(f"updated list: {updated_student_names}")
```

```python
original list: ['Francis', 'Eric']
updated list: ['Francis', 'Eric']
```

It works as expected, the list has been updated correctly, but you would notice that the original list has been edited together. What happened?

Since variables are still pointing to the same memory when they are created and assigned to a new variable, if we update one of them, then all other variables will be updated as well.

You can use a built-in function `id` to find out

```python

print(f"original list: {id(student_names)}")
print(f"updated list: {id(updated_student_names)}")
```

```python
original list: 4503145536
updated list: 4503145536
```

As a result, even if the function didn’t return anything, the result would remain the same.

```python
def update_first_value(names: List[str]):
    names[0] = "Francis"

student_names = ["Nick", "Eric"]
update_first_value(student_names)

assert student_names == ["Francis", "Eric"]
```

Another common mistake is the default argument

```python
def update_value(name: str, new_names: List[str] = []):
    new_names.append(name)
    return new_names

first_names = update_value("Nick")
print(first_names)
second_names = update_value("Eric")
print(second_names)
```

What would you expect to be like

```python
['Nick']
['Eric']
```

However, the actual result is

```python
['Nick']
['Nick', 'Eric']
```

**As a result, the mutable type is not recommended to be a default argument.**

In the above, I only take List type as examples, but you can apply the concept to all mutable types, such as dictionary and customised object.

# **Conclusion**

Python gives us the flexibility to manage variable creation, but we must understand carefully when we play around, otherwise, it might lead us down a rabbit hole.

Happy coding!
