新坑出炉:同一个函数不要传入两个一模一样的引用类型参数

背景

刷leetcode全排列(题号46)的时候,我写了如下的代码:

class Solution:
    def __init__(self):
        self.res = []

    def traverse(self, nums: List[int], track: List[int], selections: List[int]):
        if len(track) == len(nums):
            self.res.append(track)
            
            return

        for i in nums:
            # 进入节点的时候:做选择
            if i in track:
                continue
            track.append(i)
            selections.remove(i)
            self.traverse(nums, track, selections)
            # 离开节点的时候:撤销选择
            track.remove(i)
            selections.append(i)

        return

    def permute(self, nums: List[int]) -> List[List[int]]:
    	# 致命的一行代码
        self.traverse(nums, [], nums)

        return self.res

结果测试的时候,怎么跑出来都是空。最后粘贴到Pycharm上一步步调试才发现给自己挖了个大坑!

分析

因为我在调用self.traverse时,传入了三个参数,其中第一个和第三个我都是用的nums,在调试时发现当我改第三个变量selections时,第一个变量nums也会跟着变!

原因是列表是可变类型,当我指定第一个参数和第三个参数一模一样的变量时,相当于这俩变量指向了同一个地址。接下来,我不论是对第一个变量进行修改,还是对第三个变量进行修改,这俩地址都没变,改的都是这个地址里的值,所以另一个变量都会跟着变化!

修改

所以我将代码改成了如下,发现结果还是和原来一样的问题!这告诉我,python里的列表这种赋值操作,并没有创建新的对象,而是让两个列表指向了同一个对象!因此,和前面类似的,对列表的更改会反映在两个变量上。
在这里插入图片描述
再次修改终于可以了:
注意track也有一样的问题嗷!!
在这里插入图片描述

总结

再次敲黑板回顾下可变对象(引用类型)和不可变对象(值类型):

1. 可变对象:对一个变量进行操作时,其值是可变的,但是对值的修改并不会引起新的对象,即地址是不会变的,只是地址中的内容发生了变化或者地址得到了扩充!
2. 不可变对象:可以理解为一个萝卜一个坑,地址中的值是不会变的,要变就变地址!

怎么记呢?可变对象和不可变对象所说的「可变」「不可变」都是针对值而言的。值可变,说明地址不变,则是引用类型!同理,不可变对象说明值不能动,那就是值类型了。

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值