tags:

views:

237

answers:

7

So I'm teaching myself Python, and I'm having an issue with lists. I want to pass my function a list and pop items off it while retaining the original list. How do I make python "instance" the passed list rather that passing a pointer to the original one?

Example:

def burninate(b):
    c = []
    for i in range(3):
     c.append(b.pop())
    return c

a = range(6)
d = burninate(a)
print a, d

Output: [0, 1, 2] [5, 4, 3]
Desired output: [0, 1, 2, 3, 4, 5] [5, 4, 3]

Thanks!

+10  A: 

You can call burninate() with a copy of the list like this:

d = burninate(a[:])

or,

d = burninate(list(a))

The other alternative is to make a copy of the list in your method:

def burninate(b):
    c=[]
    b=b[:]
    for i in range(3):
        c.append(b.pop())
    return c

>>> a = range(6)
>>> b = burninate(a)
>>> print a, b
>>> [0, 1, 2, 3, 4, 5] [5, 4, 3]
mhawke
+6  A: 

A slightly more readable way to do the same thing is:

d = burninate(list(a))

Here, the list() constructor creates a new list based on a.

Greg Hewgill
+2  A: 

Other versions:

def burninate(b):
    c = []
    for i in range(1, 4):
        c.append(b[-i])
    return c
def burninate(b):
    c = b[-4:-1]
    c.reverse()
    return c

And someday you will love list comprehensions:

def burninate(b):
    return [b[-i] for i in range(1,4)]
Federico Ramponi
+5  A: 

A more general solution would be to import copy, and use copy.copy() on the parameter.

Jeremy Banks
If you're expecting something list-like, then it shouldn't cause any problems to just use list().
John Fouhy
+14  A: 

As other answers have suggested, you can provide your function with a copy of the list.

As an alternative, your function could take a copy of the argument:

def burninate(b):
    c = []
    b = list(b)
    for i in range(3):
        c.append(b.pop())
    return c

Basically, you need to be clear in your mind (and in your documentation) whether your function will change its arguments. In my opinion, functions that return computed values should not change their arguments, and functions that change their arguments should not return anything. See python's [].sort(), [].extend(), {}.update(), etc. for examples. Obviously there are exceptions (like .pop()).

Also, depending on your particular case, you could rewrite the function to avoid using pop() or other functions that modify the argument. e.g.

def burninante(b):
    return b[:-4:-1]   # return the last three elements in reverse order
John Fouhy
I like your reverse slice +1
mhawke
+1 for the shortest version so far
Federico Ramponi
A: 
burninate = lambda x: x[:-4:-1]
Federico Ramponi
A: 

You can use copy.deepcopy()

Alexandre Hamez