创建链表从列表

huangapple go评论63阅读模式
英文:

create Linkedlist from list

问题

我明白你的问题,以下是翻译好的部分:

问题1: 在第一种情况下,你的代码出现错误:"arrayToLL() takes 1 positional argument but 2 were given"。这是因为在类方法arrayToLL中,你没有将self作为第一个参数。你需要将方法定义改为arrayToLL(self, X),以确保它作为类的方法正确调用。

问题2: 在第二种情况下,你在arrayToLL方法中添加了self参数,但最终却没有得到预期的结果。这是因为你没有正确使用该方法。在这种情况下,你应该首先实例化LinkedList类,然后调用arrayToLL方法,如下所示:

ll = LinkedList()
ll.arrayToLL([1, 2, 3])
print(ll)

问题3: 在第三种情况下,你直接调用LinkedList.arrayToLL([1, 2, 3])方法,而没有实例化LinkedList类,却得到了正确的结果。这是因为你将arrayToLL方法定义为类方法,它可以在没有实例的情况下调用。这种方式是允许的,因为类方法不需要访问实例的属性。

所以,问题的不同结果源于方法的定义方式和调用方式。你需要根据你的需求选择合适的方式来使用这些方法。希望这能帮助你理解为什么不同情况下会出现不同的结果。

英文:

Can anyone help me understand why I get this error ?

I design a Linkedlist Class like this where I want to create a linkedlist from an array:

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

class LinkedList:
    def __init__(self, head=None):
        self.head = head

    def arrayToLL(X):
        '''Create LL from a list'''
        if not X:
            return LinkedList()
        ll = LinkedList(Node(X[0]))
        last = ll.head
        for i in range(1, len(X)):
            last.next = Node(X[i])
            last = last.next
        return ll

    def __str__(self) -> str:
        linked_list = ''
        node = self.head
        while node is not None:
            linked_list += str(node.val)
            node = node.next
            if node:
                linked_list += ' -> '
        return linked_list

When I do the implementation as I learnt for classes.
I instantiate the class first, then apply its methods

ll = LinkedList()
ll.arrayToLL([1, 2 , 3])
print(ll)

>>> I got this Error: arrayToLL() takes 1 positional argument but 2 were given

** But when I add the 'self' argument to the arrayToLL(self, X) method:
and do the previous implementation I got a blank line.
Can anyone tell me why the LL wasn't printed?? '1 -> 2 -> 3'

ll = LinkedList()
ll.arrayToLL([1, 2 , 3])
print(ll)

>>> #Blank line as result

** Another thing that confuses me is that: when I call the function arrayToLL(X) directly without instantiating the linkedlist and without using self on it the LL was printed: without error. Why this happen? what I can't use ll = LinkedList() then apply ll.methods

ll = LinkedList.arrayToLL([1, 2 , 3])
print(ll)

>>> '1 -> 2 -> 3'

What I did: I tried to add and/or remove 'self' argument in arrayToLL method an see the results.

WhatI am expecting: is to understand why in 3 cases the result change!!!
For the first case without self in arrayToLL method => I got error of missing argument
In the second case where I add the 'self' argument I got a blank result
In the third case where I remove 'self' from argument and print the method directly (LinkedList.arrayToLL([1, 2 , 3])) without instantiating the ll = LinkedList() I got the result! why this happens? Thanks

答案1

得分: 1

这段代码完成了以下功能:

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


class LinkedList:
    def __init__(self, head=None):
        self.head = head

    def array_to_ll(self, X):
        if not X:
            return self
        self.head = Node(X[0])
        curr_last = self.head
        for elt in X:
            curr_last.next = Node(elt)
            curr_last = curr_last.next
        return self

    def __str__(self):
        ll = ""
        node = self.head
        while node is not None:
            ll += str(node.val)
            node = node.next
            if node:
                ll += ' -> '
        return ll

if __name__ == "__main__":
    ll = LinkedList()
    ll.array_to_ll([1, 2, 3])
    print(ll)

在这里,你忽略了array_to_ll方法的self参数。这个参数由你调用方法的对象填充,也就是在ll.array_to_ll([1, 2, 3])中,self参数由ll填充,X参数由[1, 2, 3]填充。(实际上,第一个参数被对象填充,不管它的名字是什么,尽管在Python中强烈建议将引用方法的对象的第一个参数命名为self)。这也解释了错误消息"takes 1 positional argument, but 2 were given",因为你传递了ll[1, 2, 3],但方法只期望接收X参数。

顺便说一下,如果array_to_ll方法只用于"加载"链表而没有其他用途,你可以不返回任何内容。在你的代码和我的代码中,返回的对象也没有存储在变量中,所以它会被丢弃。这并不重要,因为我们已经有一个存储它的变量:ll。你可以将它重写为:

def array_to_ll(self, X):
    if not X:
        return    # 这仅用于在X为None时退出函数
    self.head = Node(X[0])
    curr_last = self.head
    for elt in X:
        curr_last.next = Node(elt)
        curr_last = curr_last.next
英文:

This code does the trick:

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


class LinkedList:
    def __init__(self, head=None):
        self.head = head

    def array_to_ll(self, X):
        if not X:
            return self
        self.head = Node(X[0])
        curr_last = self.head
        for elt in X:
            curr_last.next = Node(elt)
            curr_last = curr_last.next
        return self

    def __str__(self):
        ll = ""
        node = self.head
        while node is not None:
            ll += str(node.val)
            node = node.next
            if node:
                ll += ' -> '
        return ll


if __name__ == "__main__":
    ll = LinkedList()
    ll.array_to_ll([1, 2, 3])
    print(ll)

Here, you missed the self parameter of the array_to_ll method. This parameter is filled by the object you called the method with, i.e. in ll.array_to_ll([1, 2, 3]), the self parameter is filled with ll, and the X parameter is filled by [1, 2, 3]. (In fact it is the first parameter that is filled with the object, whatever its name, though it is a strong convention that this first parameter referring to the object the method is called upon should be named self in Python). This also explains the error takes 1 positional argument, but 2 were given as you gave ll and [1, 2, 3], but the method only expected X.

As a side-note, you don't have to return anything with array_to_ll if there is no other uses for this method than to "load" your linked list. (In fact, the returned object in your code and mine is not stored in a variable, so it is lost. This does not matter as we already have a variable which stores it: ll). We could then rewrite it:

def array_to_ll(self, X):
    if not X:
        return    # This is only here to exit the function in case X is None
    self.head = Node(X[0])
    curr_last = self.head
    for elt in X:
        curr_last.next = Node(elt)
        curr_last = curr_last.next

EDIT: @trincot's answer followed the other path and is also interesting to look into. While I have made this method depend on self (i.e. the instance) (which may or may not be pertinent), he made it static (i.e. depend on the class).

答案2

得分: 1

我得到了这个错误:arrayToLL()接受了1个位置参数,但给定了2个。

这是预期的,因为ll作为第一个参数传递,而你的方法没有为它定义一个参数(通常称为self)。

但是,当我向arrayToLL(self, X)方法添加self参数并执行先前的实现时,我得到了一个空行。

这是因为该方法不使用self,因此在调用后ll仍然为空。相反,该方法返回构建的链表,但然后你的主要代码没有对返回的对象进行任何操作。

当我直接调用函数arrayToLL(X)而不实例化链表并且没有在其上使用self时,链表被打印出来而没有错误。

这就是应该的方式,因为你的方法实际上与self无关。它应该被调用为一个静态方法,并且将其声明为静态方法会有意义:

    @staticmethod
    def arrayToLL(X):
        '''从列表创建LL'''
        if not X:
            return LinkedList()
        ll = LinkedList(Node(X[0]))
        last = ll.head
        for i in range(1, len(X)):
            last.next = Node(X[i])
            last = last.next
        return ll

我看到你已经创建了一个可以接受head节点作为参数的构造函数。我不会这样做。相反,你可以使用参数列表传递链表的值,这将使arrayToLL方法变得多余。此外,对于你的类,添加一个__iter__方法是有益的,__str__方法可以使用它来执行其工作,但它也可以用于其他情况。

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

class LinkedList:
    def __init__(self, *values):
        self.head = None
        for value in reversed(values):
            self.head = Node(value, self.head)

    def __iter__(self):
        node = self.head
        while node:
            yield node.val
            node = node.next
    
    def __str__(self) -> str:
        return " -> ".join(map(str, self))

ll = LinkedList(1, 2, 3)
print(ll)
英文:

> I got this Error: arrayToLL() takes 1 positional argument but 2 were given

This is expected, because ll is passed as first argument, and your method did not define a parameter for it (usually called self)

> But when I add the self argument to the arrayToLL(self, X) method: and do the previous implementation I got a blank line.

That happens because self is not used by that method, so ll is still empty after the call. Instead the method returns the built linked list, but then your main code is not doing anything with the returned object.

> when I call the function arrayToLL(X) directly without instantiating the linkedlist and without using self on it the LL was printed: without error.

This is how it should be done, because your method is not really doing anything that relates to a self. It should be called as a static method, and it would make sense to declare it that way:

    @staticmethod
    def arrayToLL(X):
        '''Create LL from a list'''
        if not X:
            return LinkedList()
        ll = LinkedList(Node(X[0]))
        last = ll.head
        for i in range(1, len(X)):
            last.next = Node(X[i])
            last = last.next
        return ll

I see that you have made a constructor that can accept a head node as argument. I would not do that. Instead you could use the argument list to pass values for the linked list, and this would make the arrayToLL method obsolete. Furthermore, it is beneficial to add an __iter__ method to your class, which the __str__ method can use to do its job, but which can also serve in other scenarios.

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

class LinkedList:
    def __init__(self, *values):
        self.head = None
        for value in reversed(values):
            self.head = Node(value, self.head)

    def __iter__(self):
        node = self.head
        while node:
            yield node.val
            node = node.next
    
    def __str__(self) -> str:
        return " -> ".join(map(str, self))


ll = LinkedList(1, 2, 3)
print(ll)

答案3

得分: -1

有一篇关于链表的好文章。https://realpython.com/linked-lists-python/

这应该会帮助你更好地理解。

英文:

There's a good article about linked lists
https://realpython.com/linked-lists-python/

That should help you gain some understanding

huangapple
  • 本文由 发表于 2023年3月9日 18:44:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/75683516.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定