Search code examples
pythonpython-3.xfunctionglobal-variables

Python list (and other objects) change when indexed inside a function


My (limited) understanding of Python is that objects defined outside a function should remain the same even if modified inside a function, i.e.

def fun():
    i=1
    return('done')

i=0
fun()
i==0 ## True

However, lists (and other objects like numpy arrays) change when indexed inside a function:

def fun():
    img[0] = img[0] + 100 
    return('done')

img = [0, 1]
fun()
img == [0, 1] ## False

Obviously I am missing a core concept with respect to how global and local variables are handled inside functions but can't seem to find any information online. Could someone please explain why objects change inside functions when indexed? Also, could someone describe how to avoid this "feature" so that when I index objects (lists, arrays, etc...) within a function, I don't inadvertently change the objects defined outside that function? Thanks!


Solution

  • Please see my recent answer to a closely related question: https://stackoverflow.com/a/69303154/8431111

    There's two concepts in play for your example:

    1. behavior of an assignment versus a reference
    2. mutating a single container object

    For item (1.) when fun assigns i = 1, it creates a new local variable due to the lack of a global declaration.

    For item (2.) let's consider this slightly simpler code instead, as it doesn't change the essential problem:

        img[0] = 100 
    

    The assignment operator locates img by first consulting the function's local scope (not found) and then finding it in the module's global scope. With a reference to the existing img object in hand, it then calls __setitem__ to alter what the zero-th element points to. In this case it will point at an immutable int object. The setter's assignment is performed by a STORE_SUBSCR bytecode instruction.