38

I am trying to implement an algorithm in Python to generate all Permutations of a list. But I In my for loop I wish to keep the original prefix and rest lists intact, and therefore I am trying to make a copy of those lists using newprefix and newrest, however on printing the variable rest at each iteration, I see that even the variable rest is getting modified! How can I make a shallow copy of the list in Python? Or is there another issue with my attempted logic?

def perm(prefix, rest):
    if len(rest) == 0:
        print prefix 
    for i in range(len(rest)):
        #prints in the for loop are just for debugging
        print "rest:", rest
        print "i=", i
        newprefix = prefix
        newprefix.append(rest[i])
        newrest = rest
        newrest.pop(i)
        print "old pre : ", prefix
        print "newpre=", newprefix
        print "newrest=", newrest
        perm(newprefix, newrest)


perm([], ['a','b','c'])
KT100
  • 1,381
  • 5
  • 17
  • 27

2 Answers2

52

To make a shallow copy, you can slice the list:

newprefix = prefix[:]

Or pass it into the list constructor:

newprefix = list(prefix)

Also, I think you can simplify your code a little:

def perm(prefix, rest):
    print prefix, rest

    for i in range(len(rest)):
        perm(prefix + [rest[i]], rest[:i] + rest[i + 1:])

perm([], ['a','b','c'])
Blender
  • 289,723
  • 53
  • 439
  • 496
  • Your first one (slicing) is my preferred way of accomplishing this. I just thought I'd let them know about the copy module as well. +1 – BlackVegetable Apr 29 '13 at 02:30
  • 6
    Just wondering - isn't the slice operation non-declarative? Isn't it best to clearly declare what you're doing? `copied_list = original_list[:]` doesn't declare that a copy is occurring, whereas `copied_list = copy.copy(original_list)` is highly declarative. – Gershom Maes Nov 18 '15 at 20:35
  • @user11580406 this is incorrect. A simple test at the Python command line will prove that `list(original)` will create a shallow copy of `original` – Jonathan Benn Feb 12 '23 at 19:52
  • If `s` is a string, why does `s[:]` produce an object with the same memory address as `s` according to [here](https://mail.python.org/pipermail/python-dev/2008-May/079694.html). In other words, `s is s[:]` if `s` is a string, but if `s` is an array, `s is not s[:]` – E. Kaufman Aug 30 '23 at 02:27
20
import copy

a = [somestuff]
b = copy.copy(a) # Shallow copy here.
c = copy.deepcopy(a) # Deep copy here.

The copy module is worth knowing about. https://docs.python.org/3/library/copy.html

(Python 2) http://docs.python.org/2/library/copy.html

BlackVegetable
  • 12,594
  • 8
  • 50
  • 82