传递给函数时链接列表的确如何表现?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了传递给函数时链接列表的确如何表现?相关的知识,希望对你有一定的参考价值。

这是我的Node类:

class Node:

 def __init__(self, value):
   self.value = value
   self.next = None

 def __repr__(self):
   if self.next == None:
     return 'Node({})'.format(repr(self.value))
   else:
     return 'Node({}, {})'.format(
       repr(self.value), repr(self.next))

这是我的方法m:

def m(lnk):
   while lnk and lnk.next:
       lnk.next = lnk.next.next
       lnk = lnk.next
   print(lnk)

然后我运行以下代码:

lnk = Node(1)
lnk.next = Node(2)
lnk.next.next = Node(3)
m(lnk)
print(lnk)

第一个输出是Node(3),第二个输出是Node(1,Node(3))。我理解第一个输出,但它是我没有真正得到的第二个输出。为什么Node(1)仍在那里?我认为lnk将作为参考传入,因此会改变并具有与我的函数中相同的值。但是,这没有发生,我不明白为什么。

答案

你现在的问题是你的m函数没有按照预期的那样做。通过删除行lnk.next = lnk.next.next来更改它:

def m(lnk):
   while lnk and lnk.next:
       lnk = lnk.next
   print(lnk)

然后,您将获得以下结果:

>>> m(lnk)
Node(3)
>>> print(lnk)
Node(1, Node(2, Node(3)))

那么,做什么呢?

__repr__说如果你是列表的最后一部分,返回“Node(#)”,其中#是值。如果您不是列表的最后一部分,请返回您下方的节点列表。

修改后的m函数现在只需打印列表中的最后一个节点。

详细了解您当前的设置以及您的m功能的作用:

当前:lnk = {'value':1,'next':{'value':2,'next':{'value':3,'next':None}}}

你的循环通过m的第一次传递采用你传入的对象,称为lnk,它定义如上,并改变它lnk = {'value':1,'next':{'value':3,'next ':None}}(因为lnk.next = lnk.next.next)。在循环中的第二次传递中,lnk变量已更改。它不再指向同一个对象;它指向对象{'value':3,'next':None},循环停止,因为'next'是None。

请注意,这修改了您的链接列表,我不认为这是意图。

Evan指出你的参考是一个很好的参考。在阅读有关内容时,您会看到函数内的变量名是本地的。它首先引用您创建的Node(1)对象,但是当您将其分配给其他对象时,它不再引用该对象。但是,它不是通过值传递的,因为您在该对象内部进行的更改(例如设置lnk.next.next)仍然存在。

创建初始链接列表时,需要使用.next.next语法来避免为每个节点创建临时变量。你也可以像这样构建你的列表:

node1 = Node(1)
node2 = Node(2)
node3 = Node(3)

node1.next = node2
node2.next = node3
linked_list = node1

现在,如果要更新lnk以指向列表的尾部,则需要返回本地变量。 m及其用法应该是这样的:

def m(node):
    while node and node.next:
        node = node.next
    return node

tail = m(lnk)

请注意,我将m的参数重命名为node。这应该可以帮助您避免混淆lnk的设置或修改位置。如果您继续修改列表,请意识到您的结果仍然相同。即使它被命名为node,行node.next = node.next.next仍然会在更高的范围内修改名为lnk的变量。

在风格说明中,我强烈建议永远不要命名功能m。给它一个名字,如get_tailget_leaf,所以很清楚这个功能是做什么的。至少你的一些困惑来自于没有明确定义m应该做什么。

如果你必须修改函数内部的lnk变量(变量本身,而不是内容),你可以使用全局变量来做,但这几乎总是一个坏主意,不应该这样做。 (因为人们习惯于变量的行为,并且改变行为会使代码更难维护。在这种情况下,大多数人都希望链接列表上的操作不具有破坏性,除非它在语义上明显是他们想要的,例如pop。)

def m():
    global lnk
    while lnk and lnk.next:
        lnk = lnk.next
另一答案

Variables in Python are not passed by reference, but by assignment.它实际上与在C或C ++中传递指针变量相同:如果更改函数内可变对象的字段,则更改将在调用范围中可见,但如果更改变量本身的标识,它不会。

以上是关于传递给函数时链接列表的确如何表现?的主要内容,如果未能解决你的问题,请参考以下文章

如何将值从其他活动传递给 viewpager 片段?

将对象列表传递给片段

如何将对象列表传递给函数,该函数需要实现接口的对象列表?

OnItemClick 如何从列表视图中获取单击项目的文本值

当我们传递一个带有一个参数的函数时,JavaScript 的 reduce 方法表现得很奇怪

如何将活动值传递给片段[重复]