1

While solving the Merge k Sorted Lists (LeetCode 23) I came out with a working code that can be summarised like this :

for key in values.keys(): 
    
        current = ListNode(key, prev)
                        
        prev = current

My question is : When passing an object to a class Initialiser (ListNode is the class and prev is the argument in question), Is it passed as reference ? So when i later change prev outside that class does it also changes in the class i just created ? Because I thought yes and I was expecting to encounter a cycle running the code above, but it actually works fine. Which means that once i pass prev to that class and then i modify prev outside, the changes do not reflect in current.

If any of you struggles with these type of concept and edge cases in the past could give me some reference or example that might help me consolidate my knowledge ?

For example passing prev to a function and then changing it in the function would it changes its value outside. Or changing it inside the class would it change it also outside ?

UPDATE: Basically my doubt is better visualised in this code :

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

first = ListNode(4, None) # 4, None
second = ListNode(3, first) # 3, 4
first = ListNode(3, None) # 3, None

print(second.next.val) # => 4

I was expecting that by printing second.next.val i would have got 3 while i still get 4. This sound very strange to me but actually looking at this other bit of code is quite intuitive :

first = 1
second = 2+first
first = 4

print(second) # => 3 
  • Nowhere in the code you show do you modify/mutate an object. *Where* did you expect that to happen? – juanpa.arrivillaga Mar 16 '22 at 18:05
  • 3
    Unless you explicitly instantiate a new object, or use something like `copy.deepcopy()`, you're passing around a reference to the same object. So, the object you created and then stored in `current`, will have a reference to the object that was passed in via `prev`. This is a very commonly asked-about topic; [this post](https://stackoverflow.com/q/986006/6273251) has a _ton_ of info about the subject, and I doubt you'll have any more questions after reading through it. – Random Davis Mar 16 '22 at 18:05
  • Thanks @RandomDavis there is a lot of good answer in that post andI think i found my answer, because i was comparing python to c++ and it seems that the way I pass prev is different from the reference (&) in c++ in python there is not exact same thing. This is what i got : basically if I change the `prev` inside the class object the changes are reflected also outside, but if I create the new `current = ListNode(prev)` and later i change the `prev` values outside, those changes are not reflected in my `current`. This is weird – Giovanni Cassanelli Mar 16 '22 at 18:54
  • 1
    I just want to clarify a bit based on your confusion. Let's say that `ListNode(prev)` creates a new ListNode, and that this new node has a reference to the other node that was passed in as `prev`. If you then change something in the `prev` node, no matter where you change it, will cause those changes to be reflected everywhere where there's a reference to that node. But if `current` had internal values that were based on the internal values of `prev`, but those values are only set upon the creation of `current`, then the values in `current` won't change when `prev` changes – Random Davis Mar 16 '22 at 19:01
  • @RandomDavis I updated the question and probably you can fully get my doubt now and yes I realise my previous comment was totally wrong. – Giovanni Cassanelli Mar 16 '22 at 19:15
  • 1
    Okay let me explain. You created a node with a value of 4 and stored its reference in the variable `first`. Then you create another node, `second`, and pass in the reference to `first`, meaning that `second`'s `next` refers to the `first` node, whose value is 4. Then, you create a new node with a value of 3, and store its reference in the variable `first`. But you never changed `second.next`; it still points to the first node you created with the value of 4. Assigning a variable to point to a different object doesn't go and change all references to that object to point to a new object instead. – Random Davis Mar 16 '22 at 19:24
  • Continuing my explanation - if, instead of `first = ListNode(3, None)`, you had just done `first.val = 3`, _then_ `second.next.val` would be 3. Or, if you'd put `second.next = first` after the `first = ListNode(3, None)` line, then `second.next.val` would be 3. The node with the value of 4 would no longer have any references to it and would thus be [garbage collected](https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)). Does that all make sense? – Random Davis Mar 16 '22 at 19:27
  • See https://nedbatchelder.com/text/names.html. The *value* of an argument is assigned to the corresponding parameter's name. – chepner Mar 16 '22 at 19:41
  • Ah yes, if you are coming from C++ the explanation is simple: Python supports **neither** call by reference nor call by value. This isn't weird at all, this is the same evaluation strategy used by many modern languages. Call by reference and call by value have mostly fallen out of style, particularly in modern, OOP languages – juanpa.arrivillaga Mar 16 '22 at 20:55
  • @RandomDavis thank you so much now I totally understand – Giovanni Cassanelli Mar 17 '22 at 19:45

0 Answers0