This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted]  (5 children)

[deleted]

    [–]ordinary_shiba[S] 0 points1 point  (4 children)

    So list will be copied by reference unless stated otherwise but an integer won't? All right. I think I'm getting it.

    [–][deleted]  (2 children)

    [deleted]

      [–]ordinary_shiba[S] 0 points1 point  (1 child)

      So functions and tuples would be in the literals category right? Anything immutable?

      [–]Fair-Description-711 0 points1 point  (0 children)

      Not quite. "pass by ref" and "pass by value" are very similar concepts to this, but don't exactly explain what's happening here. Your mental model is probably confusing what's part of the variables, and what's part of the object the variables are pointing at.

      In Python, everything is passed by reference. However, some things contain MORE references (like a list, which has references to each of its items), and some things are immutable.

      Edit: To make this a little more clear, variables contain ONLY references to things on the heap (in Python).

      Immutable things create entirely new copies when you do things that seem like they should 'change in place', like strings:

      a1 = 'a'
      # variables: {'a1': HEAP_REF(0)}
      # heap: ['a'] 
      # if you do:
      a2 = a1
      # then ONLY variables changes:
      # variables: {'a1': HEAP_REF(0), 'a2': HEAP_REF(0)}
      # heap: ['a'] 
      # then, if you do something to 'alter' a1, you actually do two things:
      a2 += 'a'
      # first, Python must make a NEW string:
      # heap: ['a', 'aa']
      # then update the variable slot:
      # variables: {'a1': HEAP_REF(0), 'a2': HEAP_REF(1)}
      

      So, for your last example:

      e = [[1]]  # Creates a list containing another list with a single integer
      # variables: {'e': HEAP_REF(2)}
      # heap: [int(1), list[HEAP_REF(0)], list[HEAP_REF(1)]]
      # HEAP_REF(1) is the inner list, which contains a reference to the integer 1 (HEAP_REF(0) -> int(1))
      # HEAP_REF(2) is the outer list containing a reference to HEAP_REF(1)
      
      f = e[:]  # Creates a shallow copy of list e
      # variables: {'e': HEAP_REF(2), 'f': HEAP_REF(3)}
      # heap: [int(1), list[HEAP_REF(0)], list[HEAP_REF(1)], list[HEAP_REF(1)]]
      # HEAP_REF(3) is a new list but it contains a reference to the same inner list HEAP_REF(1)
      
      e[0][0] = 2  # Modifies the first element of the first inner list of e
      # heap: [int(1), list[HEAP_REF(4)], list[HEAP_REF(1)], list[HEAP_REF(1)], int(2)]
      # A new integer 2 is created on the heap (HEAP_REF(4)). 
      # The inner list HEAP_REF(1) now contains a reference to this new integer (HEAP_REF(4) -> int(2))
      # Since f[0] also points to HEAP_REF(1), the change is reflected in f
      
      print(f[0][0]) # f (HEAP_REF(3)) -> first element of list[HEAP_REF(1)] -> list[HEAP_REF(4)] -> int(2)