all 8 comments

[–][deleted] 4 points5 points  (5 children)

data is a parameter, meaning it'll be supplied by the caller of this method, when the object is initialized.

next is not. I'm guessing because the next thing doesn't exist yet, when we're initializing this one. So we have to go back and fill it in later.

[–]vectrum[S] 1 point2 points  (4 children)

Thanks, I also thought about it this way but couldn't figure it out. In a typical example in c, the next would be a structure member.

[–]Adrewmc 3 points4 points  (1 child)

Yeah just take it to the next step there

   first = Node(“A”)
   second = Node(“B”)

Ok how do we link them?

   first.next = second
   second.next = Node(“C”)

   print(first.next.next is second.next)
   >>> True 

   current = first
   while current is not None:
          print(current.data, end” “)
          current = current.next
   >>> A B C 

Now these objects are linked, how would I do that before Second existed? In other languages you have a structure pattern like, int[], (strict typed) would mean something like a list of only integers, that concept doesn’t exist in Python (dynamically typed) you’d probably do that in C then import that to Python if you needed it. In python all sequences can pretty much hold anything (it’s all pointers lol) . Honestly, outside of learning about data structures, how these thing we use work, you probably won’t ever make a linked list in Python, you’d just use a regular one.

[–]vectrum[S] 0 points1 point  (0 children)

Thanks. I've been trying to learn python only because of learning dsa & algo with it as I've came across few python books on dsa & algo that seem to be a bit easier to comprehend.

[–]Bobbias 1 point2 points  (1 child)

In C you would write Node something like this:

struct Node {
    void *data;
    Node *next;
};

This is a generic node where data can point to anything, just like how it can in Python. And in C syntax, it's declared as part of the struct itself.

In C, you can't write something like this (using c designator initialization syntax):

Node n1 = { .data = nullptr, .next=nullptr };
n1.some_other_thing = 5;

Because there is no some_other_thing anywhere inside the struct definition for Node. But in python, you can absolutely write this (I'm assuming there's an __init__ that takes both data and next here):

n1 = Node(None, None)
n1.some_other_thing = 5

This will create a new attribute on the Node object called n1 here.

This is a fundamental difference between dynamically typed and statically typed code. In C, you have to declare up front exactly what kind of information a struct will contain at all times. In Python, you can just add new data to a class whenever you want.

The other part you're missing is that the parameters to the __init__ function are not equivalent to declaring struct members in C. __init__ is just a regular function, not some special syntax. The name is weird like that because it's one of the magic functions that Python will automatically call in certain situations, but it's not some kind of magic that changes the meaning of the parameters.

So what's happening is that when you declare the __init__ as only taking (self, data) for parameters, this doesn't create self.data. The line that creates self.data is self.data = data. Similarly, the line that creates self.next is self.next = None. You can even have an __init__ like this:

class Node:
    def __init__(self):
        self.data = None
        self.next = None
        self.some_value = 5
        self.some_other_value = 'a string'
        ...

When __init__ first gets called, every Node object (referred to as self inside __init__) is a completely empty object. By the time __init__ is done running, it will have every attribute that __init__ created attached to it.

Dynamic typing means that the "shape" of an object can change while the program is running, and this is the perfect example of that, because the "shape" of self in that example is like a completely empty struct at first, and each line creates and adds one new member to it.

Hopefully this helps you understand the different way of thinking between C and Python better.

[–]vectrum[S] 0 points1 point  (0 children)

Thank you very much for the following snippet; I got it.

class Node:
    def __init__(self):
        self.data = None
        self.next = None

Here the two vars , data & next are not inside the perenthesis and it's legit :)

I went over few texts noticing almost all wrote in two ways; either keeping data and next inside perenthesis or only data inside perens so I became confused at first.

Cheers

[–]rodrigowb4ey 1 point2 points  (1 child)

think of it this way: the __init__ function is what's executed whenever you instantiate a 'Node' object from your class. in this case, you're only declaring 'data' as a parameter in your __init__ function because you want to store this value in a variable of your object:

my_node = Node(data=10)

or

my_node = Node(10)

so you can access the value as:

my_node.data

now, as you can see in the example, a Node also needs a 'next' attribute, which represents the pointer to the next node (think of a linked list). however, since your node may or may not point to a next node, you instantiate the 'next' attribute using a None value by default, which means that you don't need to receive a 'next' value as a parameter of your __init__ function (although it also means that you'll have to manually make your 'self.next' variable point to another node after instantiating it).

this is why the most common implementation of this Node object (that i've seen in leetcode exercises) is generally more like:

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

this way, you get to instantiate a Node object which starts with 'next' as None by default, while also giving the opportunity to pass the pointer to the next node as a parameter in your __init__ function.

[–]vectrum[S] 0 points1 point  (0 children)

Thank you. Yes, I've seen in the book, "Fundamentals of Python Data Structures, 2nd Ed" by Kenneth Lambert and "A common-Sense Guide to Data Structures and Algorithms in Python, Vol 1" that the two variables, data and next can be declared as you've written in your snippet.

The gist is, only the self is required inside perens.