Python: why does my list change after I've retrieved it from an object
Question:   
Simple question, I've scaled down a problem I'm having where a list which I've
retrieve from an object is changing when I append more data to the object. Not
to the list.

Can anyone help my understand the behavior of python?

    
    
    class a():
        def __init__(self):
            self.log = []
        def clearLog(self):
            del self.log[:]
        def appendLog(self, info):
            self.log.append(str(info))
        def getLog(self):
            return self.log
    
    if __name__ == '__main__':
        obj = a()
        obj.appendLog("Hello")
    
        # get an instance as of this moment....
        list = obj.getLog()
        print list
    
        obj.appendLog("World")
    
        # print list, BUT we want the instance that was obtained
        # before the new appendage.   
        print list
    

**OutPut:**

    
    
    ['Hello']
    ['Hello', 'World']
    


Answer: When you code

    
    
    `list = obj.getLog()`
    

(ignoring -- just for a second -- what a **terrible** idea it is to use
identifiers that shadow builtins!!!) you're saying: "make name `list` refer to
exactly the same object that `obj.getLog()` returns" -- which as we know from
the code for `class a` is `obj.log`. So of course since now you have one list
object with two names, when you alter that object through **either** name, all
alterations will be fully visible from both names, of course -- remember,
there _is_ just **one** object, you're just using multiple names for it! You
never asked for a copy, so of course Python made no copies.

When you want a copy, instead of the original, **ask for one**! When you know
the type you require (here, a list), the best way is to call the type, i.e.:

    
    
    mylist = list(obj.getLog())
    

This of course becomes impossible if you choose to trample all over the
builtins with your identifiers -- -- which is a good part of why such
identifier choice is a **BAD** idea (I can't stress that enough: it's hard to
think of any worse style choice, to use in your Python coding, than such
naming). So, I've renamed the identifier to `mylist` (and of course you need
to rename it in the two `print` statements).

You **could** use highly unreadable or slower approaches to make up for the
wanton destruction of the normal functionality of built-in identifier `list`,
of course -- e.g.:

    
    
    import copy
    list = copy.copy(obj.getLog())   # somewhat slower
    

or

    
    
    list = obj.getLog()[:]           # traditional, but ECCH
    

or

    
    
    temp = obj.getLog()
    list = type(temp)(temp)          # abstruse
    

but **BY FAR** the simplest, cleanest, most recommended approach is to **NOT**
name your identifiers the same as Python built-ins (it's also a nice idea to
avoid naming them just like modules in the standard Python library, for
similar though a bit weaker reasons).

