Sawal Maskey
Sawal Maskey

Reputation: 648

Referencing of custom classes in Python

I understand that custom classes in Python are generally mutable. So in the example below, any changes done to the argument s in the function inc_age is reflected back at the calling section.

class Student:
    def __init__(self, name, age):
            self.name = name
            self.age = age

def inc_age(s):
    s.age += 1


s1 = Student("Test",5)
inc_age(s1)
print(s1.age) # 6

I tried to implement linked list in Python using custom class as shown below:

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

def next_node(L):
    L = L.next

end = ListNode(3)
mid = ListNode(2,end)
beg = ListNode(1,mid)

next_node(beg)
print(beg.data) # 1

My question is why the change in object L in the function next_node not observed at the calling section.

Upvotes: 0

Views: 456

Answers (2)

abarnert
abarnert

Reputation: 365767

The short version is this:

  • If you change attributes of the value in L, those will be represented in any other references to that value.
  • If you just change the local variable L to be a name for a completely different value, that doesn't change anything but the local variable L.

If this seems confusing to you, you're not thinking correctly about what variables in Python are. In some languages, like C++, a variable is a location where a value lives. In other languages, like Python, a variable is just a name that you can look up in a namespace to find a value; the values live wherever they want.

So, L = doesn't do anything to whatever value L is a name for, it just makes L into a name, in the local namespace, for a different value.

But L.next = would make next into a name for a different value in the namespace of the value that L refers to. So any other name for the same value as L can see the change.

Upvotes: 3

Reblochon Masque
Reblochon Masque

Reputation: 36682

You must address attributes using self, and avoid naming variables and attributes with the names of builtin methods (next):

  • it is also better practice to build a linked list from the head
  • In addition, I corrected a few typos

The output test enumerates all nodes from the head.

class ListNode:
    def __init__(self, data=0, next_node=None):
        self.data = data
        self.next_node = next_node

    def add_next_node(self, node):
        self.next_node = node


if __name__ == '__main__':
    beg = ListNode(1)
    mid = ListNode(2)
    end = ListNode(3)

    beg.add_next_node(mid)
    mid.add_next_node(end)

    current = beg
    while True:
        print(current.data)
        current = current.next_node
        if current is None:
            break

output:

1
2
3

Upvotes: 0

Related Questions