英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论