Python 中一切皆对象。
所谓对象,其实就对应着一块物理内存,当我们创建一个对象时,就是在内存中开辟一块区域放置一些数据,当我们要使用这块内存时,需要一个媒介,这媒介就是变量,就像一个人,他有大名、小名、书名、艺名、笔名等等,人是客观存在的,称谓是必要的,但这些称谓都是指向这个人。这是理解那些可变对象增减元素时牵一发而动全身的关键所在。
赋值语句就是给对象取称谓的过程,它的正确理解顺序是从右到左,也就是对象先被创建出来,然后再被取称谓,如下例:
a = [1, 2, 3] a = [1, 2, 3] a = [1, 2, 3]
b = a b = [1, 2, 3] a = [1, 2, 3]
左边是创建了一个对象,然后被取了多个称谓;而中间是创建了两个对象,各有称谓;而右边是先创建一个对象,取名 a,然后再创建一个对象,再取名 a,相当于和前任分手了,你再叫小甜甜时,叫的就是现任了。
Python 中,对象都有标识、类型和值。
对象的标识相当于人的身份证号,一出生被赋予后就不会改变,可以通过id()
函数获得该值;对象的类型可以,相当于变性,可以通过type()
函数获取;对象的值即它携带的数据,这也是它的存在的意义。
在实际编程中,不同对象难免被比来比去的,在 Python 中涉及到两种比较,即is
,它比较对象的标识,判定不同变量是否是同一对象,它不能被重载,直接取的id()
函数的结果;==
它比较对象的值,是a.__eq__(b)
魔术方法的语法糖,因此可以被重载。
Python 中数据复制可以大致分为等于赋值、浅复制和深复制。
等于赋值就是给对象取了别的称谓,对象始终是同一个。
浅复制是最复杂的,复杂在如果复制的对象中有可变对象子元素时,源对象和复制的对象是共享这些子对象的,它们各自的操作会相互影响。浅复制只是做了一层表面操作,在面对可变对象这样的复杂子元素时,它只是给该元素取了一个别名,然后存储了这个别名。浅复制的操作有类型构造方法如list()
、列表切片[:]
、copy.copy()
等。
深复制就是完完全全再造一个对象,复制对象和源对象完全断绝联系。深复制的操作有copy.deepcopy()
。
在 Python 的主流解释器 CPython 中,垃圾回收的主要算法是引用计数,即对象引用为零时就会被回收;后续为了解决循环引用的问题,引入了分代回收算法。
对象是因为有了引用才会在内存中存在,引用对应着对象的称谓也就是别名,del
语句用于删除别名,而不是直接删除掉对象,当对象引用清零被删除时,解释器会调用对象的__del__
特殊方法,因此可以重载该方法做一些善后工作。正常的引用比如赋值会增加对象的引用计数,当我们不希望一些无关紧要的引用影响对象的正常回收时,可以使用弱引用的方式,弱引用不会增加引用计数,比如对象做缓存时,系统暂时需要但不需要一直存在,就很适合这样的场景。