Mutable vs. immutable objekty¶

Datové typy v Pythonu se podle svých vlastností dělí na:

  1. mutable (modifikovatelné) – např. list, set, dict
  2. immutable (nemodifikovatelné) – např. str, tuple, frozenset, všechny číselné datové typy

Modifikovatelné typy mají metody, které umožňují modifikovat daný objekt (např. přidávat nebo odebírat prvky v kontejneru). Naopak nemodifikovatelné typy nemají žádné metody, které by modifikovaly daný objekt – jediný způsob, jak dosáhnout modifikace, je tedy vytvoření nového objektu.

Přiřazení mutable objektů¶

In [14]:
# přiřazení immutable objektů ... číslo
a = 10
b = a
print(a is b)  # `a` a `b` jsou identické

# změna immutable objektu
b +=  2

print("a =", a)  # vypíše 10
print("b =", b)  # vypíše 12
print(a is b)    # False
print(a == b)    # False
True
a = 10
b = 12
False
False
In [2]:
# přiřazení immutable objektů ... tuple
a = (10, 5)
b = a
print(a is b)  # `a` a `b` jsou identické

# změna immutable objektu
b +=  (1, 2)

print("a =", a)  # vypíše (10, 5)
print("b =", b)  # vypíše (10, 5, 1, 2)
print(a is b)    # False
print(a == b)    # False
True
a = (10, 5)
b = (10, 5, 1, 2)
False
False
In [15]:
# přiřazení mutable objektů ... list
a = [10, 5]
b = a
print(a is b)  # `a` a `b` jsou identické

# změna mutable objektu
b.extend([1, 2])

print("a =", a)  # vypíše [10, 5, 1, 2]
print("b =", b)  # vypíše [10, 5, 1, 2]
print(a is b)    # True
print(a == b)    # False
True
a = [10, 5, 1, 2]
b = [10, 5, 1, 2]
True
True
In [5]:
# přiřazení mutable objektů ... set
a = {10, 5}
b = a
print(a is b)  # `a` a `b` jsou identické

# změna mutable objektu
b.add(1)

print("a =", a)  # vypíše {1, 10, 5}
print("b =", b)  # vypíše {1, 10, 5}
print(a is b)    # True
print(a == b)    # False
True
a = {1, 10, 5}
b = {1, 10, 5}
True
True

Volání funkcí¶

In [18]:
# podobně pro volání funkce, kde je mutable objekt argumentem
def f(t):
    t.append(1)
    t.sort()
    print("lokální:", t)

s = [1, 7, 2, 4]
f(s)
print("globální:", s)
lokální: [1, 1, 2, 4, 7]
globální: [1, 1, 2, 4, 7]
In [19]:
# globální immutable objekt se uvnitř funkce nezmění
def f(t):
    t += (1, 2)
    print("lokální:", t)

s = (1, 7, 2, 4)
f(s)
print("globální:", s)
lokální: (1, 7, 2, 4, 1, 2)
globální: (1, 7, 2, 4)
In [12]:
# globální immutable objekt se uvnitř funkce nezmění
def f(x):
    x += 3
    print("lokální:", x)

x = 4
f(x)
print("globální:",x)
lokální: 7
globální: 4

Kopírování mutable objektů¶

In [1]:
def copy_list(source):
    """ Creates a new list containing all elements of the source.
        Does **not** modify the parameter.
    """
    copy = []
    for element in source:
        copy.append(element)
    return copy
In [16]:
a = [1, 3]

b1 = copy_list(a)
b2 = list(a)
b3 = a.copy()
b4 = a[ : ]

print(a is b1, a is b2, a is b3, a is b4)
a.append(2)
print(a)  
print(b1, b2, b3, b4)  
False False False False
[1, 3, 2]
[1, 3] [1, 3] [1, 3] [1, 3]
In [12]:
a = {1, 3}

b1 = set(a)
b2 = a.copy()

print(a is b1, a is b2)
a.add(2)
print(a)  
print(b1, b2) 
False False
{1, 2, 3}
{1, 3} {1, 3}
In [13]:
a = {1: "a", 3: "b"}

b1 = dict(a)
b2 = a.copy()

print(a is b1, a is b2)
a[5] = "c"
print(a)  
print(b1, b2) 
False False
{1: 'a', 3: 'b', 5: 'c'}
{1: 'a', 3: 'b'} {1: 'a', 3: 'b'}