Jak klonovat nebo kopírovat seznam?

Jaké jsou možnosti klonování nebo kopírování seznamu v jazyce Python?

Při použití new_list = my_list se při jakékoli změně new_list vždy změní my_list. Proč tomu tak je?

Řešení

Při použití new_list = my_list ve skutečnosti nemáte dva seznamy. Přiřazení pouze kopíruje odkaz na seznam, nikoliv skutečný seznam, takže jak new_list, tak my_list odkazují po přiřazení na stejný seznam.

Chcete-li seznam skutečně zkopírovat, máte různé možnosti:

  • Můžete použít vestavěnou metodu list.copy() (k dispozici od verze Python 3.3):

      Nový_seznam = starý_seznam.kopírovat()
  • Můžete jej nakrájet na plátky:

      new_list = old_list[:]

    Alex Martelli's názor (alespoň [v roce 2007][2]) na to je, že je to divná syntaxe a nemá smysl ji nikdy používat. ;) (Podle jeho názoru je další čitelnější).

  • Můžete použít vestavěnou funkci list():

      nový_seznam = seznam(starý_seznam)
  • Můžete použít obecnou funkci copy.copy():

      import copy
      new_list = copy.copy(old_list)

    Tento postup je o něco pomalejší než list(), protože musí nejprve zjistit datový typ old_list.

  • Pokud seznam obsahuje objekty a chcete je také zkopírovat, použijte obecný copy.deepcopy():

      import copy
      new_list = copy.deepcopy(old_list)

    Zřejmě nejpomalejší a paměťově nejnáročnější metoda, ale někdy se jí nelze vyhnout.

Příklad:

import copy

class Foo(object):
    def __init__(self, val):
         self.val = val

    def __repr__(self):
        return str(self.val)

foo = Foo(1)

a = ['foo', foo]
b = a.copy()
c = a[:]
d = list(a)
e = copy.copy(a)
f = copy.deepcopy(a)

# edit orignal list and instance 
a.append('baz')
foo.val = 5

print('original: %r\n list.copy(): %r\n slice: %r\n list(): %r\n copy: %r\n deepcopy: %r'
      % (a, b, c, d, e, f))

Výsledek:

original: ['foo', 5, 'baz']
list.copy(): ['foo', 5]
slice: ['foo', 5]
list(): ['foo', 5]
copy: ['foo', 5]
deepcopy: ['foo', 1]
Komentáře (11)

Použít věc[:]

>>> a = [1,2]
>>> b = a[:]
>>> a += [3]
>>> a
[1, 2, 3]
>>> b
[1, 2]
>>> 
Komentáře (0)

Pythonovský idiom pro tento postup je newList = oldList[:].

Komentáře (0)