【python】可变对象与非可变对象

在Python中任何对象都有的三个通用属性:唯一标识,类型,值。

唯一标识:用于标识对象的在内存中唯一,它在对象创建之后就不会再,函数可以查看对象的唯一标识 id()

类型:决定了该对象支持哪些操作,不同类型的对象支持的操作就不一样,比如列表可以有长度属性,而整数没有同样地对象的类型一旦确定了就不会再变,函数可以报道查看对象的类型信息。 type()

对象与唯一标识不一样,并不是所有的对象的值都是一成不变的,有些对象的值可以通过某些操作发生改变,值可以变化的对象称之为可变对象(可变),值不能改变的对象称之为不可变对象(不可变)

不可变对象:对于不可变对象,值永远是刚开始创建时候的值,对该对象做的任何操作都会导致一个新的对象的创建。常见的不可变对象有:int,float,tuple, set, str

可变对象:可变对象的值可以通过某些操作动态的改变,比如列表对象,可以通过append方法不断地往列表中添加元素,该列表的值就在不断的处于变化中,一个可变对象赋值给两个变量时,他们共享同一个实例对象,指向相同的内存地址,对其中任何一个变量操作时,同时也会影响另外一个变量。常见的可变对象有list,dict。

举例1:赋值语句


说明:x=6. 左边的是指向,右边的是一个对象(对象)或者一个有指向对象的指向,可以有多个指向指向同一个对象(对象),[注意此地对象的意思,可以是值,实例,函数等等],综上,此地时建立了一个叫x的变量(变量)

上面操作的对象是不可变对象.b = a,可以表示a和b都指向整型1,即他们有相同的地址,当a = 2时,由于a是补课班变量a=2改变了a的值就相当于改变了a的指向的地址。而b指向的地址还是要原来整型1的地址,即此时a!=b。

下面对比下可变对象:


可以看到此时一个和b的值一样,由于a和b都是同一地址,当a为可变量时,a的值发生改变时是在原地址上的值改变了,所以结果a和b最后还是相同的。

举例2:自加语句 (a+=1与a=a+1是否真的一样)


上面可以看出L2+ =1与L2 = L2 + 1会产生不同的结果,虽然值相同但是已经是不同的对象了

讲到上面的不同原因先来看看__add__和__iadd__ 的区别

  • __add__方法接收两个参数,返回它们的和,两个参数的值均不会改变。

  • __iadd__方法同样接收两个参数,但它是属于in-place操作,就是说它会改变第一个参数的值,因为这需要对象是可变的,所以对不可变对象没有__iadd__方法。

+=  首先操作会尝试调用对象的  __iadd__ 方法,如果没有该方法,尝试那么调用 __add__ 方法。

但是整数对象没有__iadd方法,而列表对象提供了__iadd__方法。

代码L2 + = [3]操作调用了--iadd__方法,他会原地址的修改L2的指向的那个对象本身的值

如下图所示:此时L1和L2还是指向同一个对象

但是代码L2 = L2 + [3]中的操作是调用的是__add__方法,该方法会返回一个新的对象,原来的对象保持不变,L1还是指向原来的对象,L2却指向了一个新的对象。

如下图所示:

以上就是表达式i + = x与i = i + x的区别。因此对于列表进行+ =操作时,会存在潜在的bug,因为l1会因为l2的变化而发生改变,就像函数的参数不宜使用可变对象作为关键字参数一样。

注:因为整型没有__iadd__方法,所以不管是a=1,a+=1还是a=a+1,最终结果都是用方法__add__,结果都是指向新的对象。


参考:https //mp.weixin.qq.com/s/jluii9YIvfhKd_tPecfTaw

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值