代码1与代码2中的l2的值是一样的,但是l1的值却不一样,说明i += x与i = i + x是不等价的,那什么情况下等价,什么情况下不等价呢?
弄清楚这个问题之前,首选得明白两个概念:可变对象与不可变对象。
在 Python 中任何对象都有的三个通用属性:唯一标识、类型、值。
唯一标识:用于标识对象的在内存中唯一性,它在对象创建之后就不会再改变,函数id()可以查看对象的唯一标识
类型:决定了该对象支持哪些操作,不同类型的对象支持的操作就不一样,比如列表可以有length属性,而整数没有。同样地对象的类型一旦确定了就不会再变,函数type()可以返回对象的类型信息。
对象的值与唯一标识不一样,并不是所有的对象的值都是一成不变的,有些对象的值可以通过某些操作发生改变,值可以变化的对象称之为可变对象(mutable),值不能改变的对象称之为不可变对象(immutable)
不可变对象(immutable)
对于不可变对象,值永远是刚开始创建时候的值,对该对象做的任何操作都会导致一个新的对象的创建。
整数 “1” 是一个不可变对象,最初赋值的时候,a指向的是整数对象 1 ,但对变量a执行+=操作后, a 指向另外一个整数对象 2 ,但对象 1 还是在那里没有发生任何变化,而 变量 a 已经指向了一个新的对象2。常见的不可变对象有:int、tuple、set、str。
可变对象(mutable)
可变对象的值可以通过某些操作动态的改变,比如列表对象,可以通过append方法不断地往列表中添加元素,该列表的值就在不断的处于变化中,一个可变对象赋值给两个变量时,他们共享同一个实例对象,指向相同的内存地址,对其中任何一个变量操作时,同时也会影响另外一个变量。
执行append操作后,对象的内存地址不会改变,x、y 依然指向的是原来同一个对象,只不过是他的值发生了变化而已。
理解完可变对象与不可变对象后,回到问题本身,+=与+的区别在哪里呢?
+= 操作首先会尝试调用对象的 __iadd__方法,如果没有该方法,那么尝试调用__add__方法,先来看看这两个方法有什么区别
__add__和__iadd*__*的区别**
__add__ 方法接收两个参数,返回它们的和,两个参数的值均不会改变。
__iadd__ 方法同样接收两个参数,但它是属于 in-place 操作,就是说它会改变第一个参数的值,因为这需要对象是可变的,所以对于不可变对象没有__iadd__方法。
显然,整数对象是没有__iadd__的,而列表对象提供了__iadd__方法。
l2 += [3]#代码1:使用__iadd__,l2的值原地修改
代码1中的 += 操作调用的是__iadd*__*方法,他会原地修改l2指向的那个对象本身的值
(1)Python所有方向的学习路线(新版)
这是我花了几天的时间去把Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
最近我才对这些路线做了一下新的更新,知识体系更全面了。
(2)Python学习视频
包含了Python入门、爬虫、数据分析和web开发的学习视频,总共100多个,虽然没有那么全面,但是对于入门来说是没问题的,学完这些之后,你可以按照我上面的学习路线去网上找其他的知识资源进行进阶。
(3)100多个练手项目
我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了,只是里面的项目比较多,水平也是参差不齐,大家可以挑自己能做的项目去练练。