提问人:FrankC 提问时间:7/5/2023 最后编辑:FrankC 更新时间:7/5/2023 访问量:73
Python 函数的副作用
Side Effects of Function in Python
问:
我是一个相当新手的程序员,目前正在尝试解决 Leetcode 上的“回文链表”程序。我的想法是编写一个名为“reverse”的嵌套函数,它反转链表,然后简单地执行比较。代码附在下面。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def isPalindrome(self, head: Optional[ListNode]) -> bool:
def reverse(arg):
#function to return a reverse of the linked list
curr, prev = arg, None
while curr:
nxt = curr.next
curr.next = prev
prev = curr
curr = nxt
return prev
original = head
reversed_ = reverse(original)
return head == reversed_
经过一些调试,我确定我的函数似乎工作正常。但是,当我调用反向时:reverse()
reversed_ = reverse(original)
它有一个意想不到的副作用,即更改 AND 的值。当我在以下输入上运行此代码时:original
head
head = [1,2,2,1]
然后当我到达最后一行时,具有正确的值,但 head 已被函数调用更改为只是reversed_
head = [1]
我知道这就是所谓的副作用,我现在第一次感受到了函数式编程的吸引力。我能做些什么来纠正这种情况?我尝试引入变量来处理这个问题,但无济于事。original
答:
查看代码的这一部分:
original = head
reversed_ = reverse(original)
return head == reversed_
第一行将名为“head”的值命名为“original”,但“head”和“original”都是同一值的名称(可能是 )。ListNode
第二行调用 ,但这与调用 相同。该函数继续更改链表中以 开头的所有对象。结果是一个反转的链表,但由原始链表中的相同元素构成 - 并且由于链表由其部分定义,因此原始链表不再存在。reverse
original
reverse(head)
reverse()
ListNode
head
因此,将是 ,因为它将生成的反转链表与以反转链表的最后一个元素为标题的链表进行比较。(这是假设已经正确定义了它)head == reversed_
false
ListNode
__eq__()
为了避免这种情况,您需要首先创建链表的完整副本,然后将其反转,然后比较两个生成的链表(以遵循您提出的逻辑)。或者,您可以通过创建 as you go 的副本来构造反向链表。很难说最好的选择是什么,因为它取决于 .ListNode
ListNode
还要考虑可能有更有效的解决方案,可以在不构造副本的情况下对原始链表执行比较,尤其是在您知道链表的长度的情况下。
评论
original = head
创建为新的变量名称,但该名称引用的对象与 : 不同,它不会创建第二个链表。要按照您想要的方式继续,您需要编写一个函数来复制列表。original
head
head
head[:]
reverse
array
list
list
array