如何克隆或复制列表?

在Python中克隆或复制列表有哪些选项?

每次my_list更改时,使用new_list = my_list然后修改new_list
为什么是这样?


new_list = my_list ,你实际上没有两个列表。 分配只是将引用复制到列表中,而不是实际列表,因此new_listmy_list在分配后引用同一个列表。

要真正复制列表,您有各种可能性:

  • 你可以切片:

    new_list = old_list[:]
    

    亚历克斯马尔泰利的观点(至少在2007年)是这样的,它是一种奇怪的语法,它永远不会使用它。 ;)(在他看来,下一个更具可读性)。

  • 您可以使用内置的list()函数:

    new_list = list(old_list)
    
  • 您可以使用通用copy.copy()

    import copy
    new_list = copy.copy(old_list)
    

    这比list()慢一点,因为它必须先找出old_list的数据类型。

  • 如果列表包含对象并且您想要复制它们,请使用generic copy.deepcopy()

    import copy
    new_list = copy.deepcopy(old_list)
    

    显然是最慢和最需要记忆的方法,但有时是不可避免的。

  • 例:

    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[:]
    c = list(a)
    d = copy.copy(a)
    e = copy.deepcopy(a)
    
    # edit orignal list and instance 
    a.append('baz')
    foo.val = 5
    
    print('original: %rn slice: %rn list(): %rn copy: %rn deepcopy: %r'
          % (a, b, c, d, e))
    

    结果:

    original: ['foo', 5, 'baz']
    slice: ['foo', 5]
    list(): ['foo', 5]
    copy: ['foo', 5]
    deepcopy: ['foo', 1]
    

    费利克斯已经提供了一个很好的答案,但我认为我会对各种方法进行速度比较:

  • 10.59秒(105.9us / itn) - copy.deepcopy(old_list)
  • 10.16秒(101.6us / itn) - 使用deepcopy复制类的纯python Copy()方法
  • 1.488秒(14.88us / itn) - 纯python Copy()方法不复制类(只有字符串/列表/元组)
  • 0.325秒(3.25us / itn) - for item in old_list: new_list.append(item)
  • 0.217秒(2.17us / itn) - [i for i in old_list] (列表理解)
  • 0.186秒(1.86us / itn) - copy.copy(old_list)
  • 0.075秒(0.75us / itn) - list(old_list)
  • 0.053秒(0.53us / itn) - new_list = []; new_list.extend(old_list) new_list = []; new_list.extend(old_list)
  • 0.039秒(0.39us / itn) - old_list[:] (列表切片)
  • 所以最快的是列表切片。 但请注意copy.copy()list[:]list(list) ,不像copy.deepcopy()和python版本不会复制列表中的任何列表,字典和类实例,所以如果原始文件,它们也会在复制列表中更改,反之亦然。

    (如果任何人有兴趣或想提出任何问题,这里是脚本:)

    from copy import deepcopy
    
    class old_class:
        def __init__(self):
            self.blah = 'blah'
    
    class new_class(object):
        def __init__(self):
            self.blah = 'blah'
    
    dignore = {str: None, unicode: None, int: None, type(None): None}
    
    def Copy(obj, use_deepcopy=True):
        t = type(obj)
    
        if t in (list, tuple):
            if t == tuple:
                # Convert to a list if a tuple to 
                # allow assigning to when copying
                is_tuple = True
                obj = list(obj)
            else: 
                # Otherwise just do a quick slice copy
                obj = obj[:]
                is_tuple = False
    
            # Copy each item recursively
            for x in xrange(len(obj)):
                if type(obj[x]) in dignore:
                    continue
                obj[x] = Copy(obj[x], use_deepcopy)
    
            if is_tuple: 
                # Convert back into a tuple again
                obj = tuple(obj)
    
        elif t == dict: 
            # Use the fast shallow dict copy() method and copy any 
            # values which aren't immutable (like lists, dicts etc)
            obj = obj.copy()
            for k in obj:
                if type(obj[k]) in dignore:
                    continue
                obj[k] = Copy(obj[k], use_deepcopy)
    
        elif t in dignore: 
            # Numeric or string/unicode? 
            # It's immutable, so ignore it!
            pass 
    
        elif use_deepcopy: 
            obj = deepcopy(obj)
        return obj
    
    if __name__ == '__main__':
        import copy
        from time import time
    
        num_times = 100000
        L = [None, 'blah', 1, 543.4532, 
             ['foo'], ('bar',), {'blah': 'blah'},
             old_class(), new_class()]
    
        t = time()
        for i in xrange(num_times):
            Copy(L)
        print 'Custom Copy:', time()-t
    
        t = time()
        for i in xrange(num_times):
            Copy(L, use_deepcopy=False)
        print 'Custom Copy Only Copying Lists/Tuples/Dicts (no classes):', time()-t
    
        t = time()
        for i in xrange(num_times):
            copy.copy(L)
        print 'copy.copy:', time()-t
    
        t = time()
        for i in xrange(num_times):
            copy.deepcopy(L)
        print 'copy.deepcopy:', time()-t
    
        t = time()
        for i in xrange(num_times):
            L[:]
        print 'list slicing [:]:', time()-t
    
        t = time()
        for i in xrange(num_times):
            list(L)
        print 'list(L):', time()-t
    
        t = time()
        for i in xrange(num_times):
            [i for i in L]
        print 'list expression(L):', time()-t
    
        t = time()
        for i in xrange(num_times):
            a = []
            a.extend(L)
        print 'list extend:', time()-t
    
        t = time()
        for i in xrange(num_times):
            a = []
            for y in L:
                a.append(y)
        print 'list append:', time()-t
    
        t = time()
        for i in xrange(num_times):
            a = []
            a.extend(i for i in L)
        print 'generator expression extend:', time()-t
    

    编辑 :添加新样式,旧式的类和字符串的基准,并使python版本更快,并添加了一些更多的方法,包括列表表达式和extend()


    我听说Python 3.3+增加了list.copy()方法,它应该像切片一样快:

    newlist = old_list.copy()

    链接地址: http://www.djcxy.com/p/3135.html

    上一篇: How to clone or copy a list?

    下一篇: How to concatenate two lists in Python?