python可变_python 可变/不可变对象、+=和=+

刷lc题的时候,老踩这种坑,索性搞懂。

先有概念:

1、python里面的所有元素都是对象,实例化一个对象就会开辟新的内存空间,然后返回一个引用给你。

2、a = 3。这里实例化了一个对象3,用变量名a表示。需要明确a不是对象本身,a只是这个对象3的引用。(回忆一下c++里面的指针和引用)

可变对象和不可变对象

可变对象和不可变对象的本质区别就是:对象本身的值可不可变。

可变对象:可变对象的值是可以原地 (inplace) 改变的,我们可以通过引用 (变量名) 来操作可变对象,使得它的值原地变化(即不开辟新的内存空间,地址不变)。

包括:list、set、dict(添加值我们不把它看成开辟“新”的内存空间,因为地址没变)。

不可变对象:不可变对象的值是不能改变的。如果引用 (变量名) 如果想要改变值,那不好意思,请你找新的对象去吧!(也就是会实例化新的对象,开辟新的内存空间,产生一个新的地址)

包括:int、str、float、tuple

Demo(此图出现太多,不明出处):不可变对象 int可变对象 list

+= 和 =+

这两个操作符,和可变/不可变对象有密切联系。

+=:调用对象的__iadd__方法,若不存在,才调用__add__方法;

=+:直接调用对象的__add__方法。

__iadd__方法直接在原地 (inplace) 修改对象的值,返回值为None,因此引用的地址不变;而__add__方法会返回一个新的对象,原对象不变。

和可变/不可变对象的联系:

一般情况下,可变对象有__iadd__方法,而不可变对象只有__add__方法。

另:对list而言,+= 和 extend() 等价。

Demo:

坑2:dp初始化二维数组时,下面注释里面那种写法是错的。

class Solution:

def longestCommonSubsequence(self, text1: str, text2: str) -> int:

LA, LB = len(text1), len(text2)

# dp = [[0]*(LB+1)]*(LA+1) ##########这里!!

dp = [[0]*(LB+1) for _ in range(LA+1)]

for i in range(LA-1,-1,-1):

for j in range(LB-1,-1,-1):

if text1[i] == text2[j]:

dp[i][j] = dp[i+1][j+1] + 1

else:

dp[i][j] = max(dp[i][j+1], dp[i+1][j])

return dp[0][0]

为什么呢?因为int是不可变对象,复制出来都是新的对象,所以第一维没有问题。而list复制的只是引用,第二维看似复制了很多次,实际上都指向同一个对象。

所以可以用*复制不可变对象,但千万不要用来复制可变对象!错误(左),正确(右)

深Copy和浅Copy

这篇文章写得很好,就不重复造轮子了。张小鸡:5张图彻底理解Python中的浅拷贝与深拷贝​zhuanlan.zhihu.com621f16451674acff66805f3f3c81a422.png

总结一下:

1、赋值

赋值操作,其实就是给一段内存地址贴标签。

对于不可变对象,=、copy、deepcopy三者等价。

2、浅拷贝

拷贝父对象的副本,但不会拷贝对象的内部的子对象。

或者说浅拷贝只是拷贝了原始元素的引用(内存地址),拷贝对象的值是否会随着被拷贝对象变化,仅取决于原始元素是可变对象还是不可变对象。

3、深拷贝

完全拷贝了父对象及其子对象。

深拷贝复制的不只是原始元素的引用,而是整个原始元素对象。因此,拷贝对象和被拷贝对象的值相互独立。

参考:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值