彻底理解Python中对象、对象与变量引用的关系

2023-06-16 0 520

在Python里,大部份人皆第一类,全然的面向第一类。

Python中,大部份的原素都是第一类。(第一类是三个抽象化,可想像成现实生活中的三个前述球体。)

1.甚么是第一类?

第一类的其本质是:

第一类是重新分配的几块内存,有足够多的内部空间去表示它所代表者的值。—— 《Learning Python》

换句话说:几块内存内部空间,保有某一的值,全力支持某一类别的有关操作方式[1]

2.第一类的特征:

Python中,第一类具备二律背反:标记(identity)、类型(type)、值(value)。

彻底理解Python中对象、对象与变量引用的关系

标记(identity):

用作惟一标记第一类,一般来说有关联第一类在计算机系统内存中的门牌号。采用内建表达式id(obj)回到第一类惟一标记。

类别(type):

第一类中所含国际标准的颈部重要信息:类别标记符。标记第一类类别,则表示第一类储存的统计数据的类别。

类别能管制第一类的值域覆盖范围和可继续执行的操作方式。采用内建表达式type(obj)回到第一类辖下类别。

每三个第一类都有三个国际标准的颈部重要信息:

1.类别标记符,去标记对象的(统计数据)类别;

2.提及计时器,历史记录现阶段第一类的提及的数量。

(拆解监督机制:表达式的提及计时器为0,手动清扫。 ※ 较细整数型第一类有内存监督机制。)

值(value):

则表示第一类储存的统计数据的重要信息。采用内建表达式print(obj)能直接打印值。

再看一遍图

彻底理解Python中对象、对象与变量引用的关系

操作方式符is 和==的区别与亲密关系:

is

判断三个表达式是否指向同三个第一类,比较三个提及是否代表者了内存中同三个门牌号,是否指向同几块内存内部空间。通过id(obj)回到值判断。

==

比较第一类的本身内容{类别(type)和值(value)}是否一致。默认会调用第一类的__eq__方法。

亲密关系:

当id相同时,is 为True,两者的type和value肯定相同,

但当type与value相同时,== 为True,但两者的id不一定相同。

例如:

列表

>>> a = [1,2] >>> b = [1,2] >>> a == b True >>> a is b False >>> id(a) 4544053632 >>> id(b) 4544054976

整数

>>> c = 257 >>> d = 257 >>> c == d True >>> c is d False >>> id(c) 4543126928 >>> id(d) 4543123664

小整数 small_ints 和 短字符串 内存池

CPython出于性能优化的考虑,把频繁采用的整数第一类用三个small_ints的第一类池内存起来。

small_ints内存的整数值被设定为[-5, 256]这个区间。

如果采用CPython解释器,在任何提及这些整数的地方,都不需要重新创建int第一类,而是直接提及内存池中的第一类。

如果整数不在该覆盖范围内,那么即便三个整数的值相同,它也是不同的第一类。

例如:

小整数

>>> a = 1 >>> b = 1 >>> id(a) 4316985648 >>> id(b) 4316985648 # small_ints [-5, 256]这个区间的数值已内存,所以表达式提及内容相同的第一类,id相同。 >>> c = 257 >>> d = 257 >>> id(c) 4334697040 >>> id(d) 4334697808 # 不属于 small_ints 区间的数字,表达式提及内容相同的第一类,id不同。

短字符串[2]

>>> a = good >>> b = good >>> a is b True #长字符串则会显示不同 False >>> c = very good >>> d = very good >>> c is d False

3.第一类的分类:难点

Python第一类系列:可变第一类和不可变第一类

4.第一类的储存和创建:

Python中,第一类储存在堆(heap)内存中。第一类通过调用__new__创建。

5.表达式:

甚么是表达式?

表达式是三个系统表的原素,保有指向第一类的连接的内部空间。——《Learning Python》

Python中,表达式用来指向任意的第一类,是第一类的提及。Python表达式更像是指针,而不是统计数据储存区域。

表达式,看作第一类的三个临时「标签」,是提及,而不是装有第一类的容器[3]

例如:

房间门外挂着“张先生的房间”的门牌,

矿泉水瓶身上贴的一张写着“刘女士的矿泉水”的标签。

给三个表达式赋值,把这个标签贴到三个第一类上,重新赋值,是撕下标签贴到另三个第一类上。

彻底理解Python中对象、对象与变量引用的关系

上图给2个表达式赋给一样的值,就相当于把2个标签贴在同三个第一类上,代码如下:

>>> a = 1 >>> print(“a = “, a ,\tid(a):”,id(a)) a = 1 id(a): 4376021296 >>> b = 2 >>> print(“b = “, b ,\tid(b):”,id(b)) b = 2 id(b): 4376021328 >>> c = 1 >>> print(“c = “, c ,\tid(c):”,id(c)) c = 1 id(c): 4376021296 # 把标签 a 从第一类 1 撕下来,再贴到第一类 2 上。 >>> a = 2 >>> print(“a = “, a ,\tid(a):”,id(a)) a = 2 id(a): 4376021328 >>> print(“b = “, b ,\tid(b):”,id(b)) b = 2 id(b): 4376021328 # a 和 c 开始指向同三个第一类,重新赋值之后,a 又和 b 指向同三个第一类。

※ 赋值(=)操作方式就是第一类标记(identity)的传递,片面的认知是内存门牌号的传递。

表达式一旦采用完毕,可被清扫(撕掉标签)。

6.提及:

提及是手动形成的从表达式到第一类的指针。——《Learning Python》

在Python中,赋值(=)操作方式时,从表达式到第一类手动建立的连接亲密关系,称为提及。

提及是一种亲密关系,以内存中的指针的形式实现。

6.1赋值语句:

Python赋值语句中,当把一个第一类赋给三个统计数据结构原素或者表达式名时,Python总是会储存第一类的提及,而不是第一类的三个拷贝。

赋值操作方式符 =

定义表达式的= 与数学中的= 意义不同。

Python 中的等号左边是表达式名字,右边是第一类值,= 则表示将右边的值传递给左边。

所以 = 是右连接性,第一类值的传递顺序是从右到左。

6.2 提及方式:

6.2.1 简单提及:

三个第一类 3 (int整数型,不可变第一类),用表达式名 a 则表示:

a = 3

Python中,从概念上,a = 3 反映大部份赋值语句继续执行的三个步骤:

创建三个第一类来代表者值 3 。

2.创建三个表达式 a ,如果它还没有创建的话。

3.将表达式 a 与 新的第一类 3 相连接。

彻底理解Python中对象、对象与变量引用的关系

※ 需要明确 a 不是第一类本身, a 只是第一类 3 的提及。

6.2.2 共享提及

a = 3 b = a
彻底理解Python中对象、对象与变量引用的关系

a 指向第一类3,b = a 赋值提及,于是 b 也指向3。

a 和 b 都共同提及了同三个第一类 3。

然后,a 重新指向三个新第一类spam(字符串,不可变第一类),b 依然指向第一类 3。

a = 3 b = a a = spam
彻底理解Python中对象、对象与变量引用的关系

列表的共享提及

>>> a = b = [1, 2] >>> c = [1,2] >>> a is b True >>> a == c True >>> a is c False >>> id(a) 4370623360 >>> id(b) 4370623360 >>> id(c) 4370521728 # 第一行,表达式 a 与 b 赋值时,共同提及同三个第一类[1,2],id()相同。 # 第二行,表达式 c 再次创建三个第一类,类别为列表,值为[1,2]。 # c 提及的第一类 id() 是新创建的,与 a 和 b 提及的第一类 id() 不同。

局部表达式:

局部表达式,被临时保存在三个叫栈(Stack)的内存中(或寄存器中),一旦采用完毕,栈就会被清扫释放掉,局部表达式就随之消失。

内存中的堆栈和统计数据结构堆栈不是三个概念,能说内存中的堆栈是真实存在的物理区,统计数据结构中的堆栈是抽象化的统计数据储存结构。[4]

内存内部空间在逻辑上分为三部分:

1.代码区:储存方法体的二进制代码。

2.静态统计数据区:储存全局表达式、静态表达式、常量(包括final修饰的常量和String常量)。系统手动重新分配和拆解。

3.动态统计数据区:

3.1堆区:_new_三个第一类的提及/门牌号储存在栈区,指向该第一类储存在堆区中的真实统计数据。

3.2栈区:储存运行方法的形参、局部表达式、回到值。由系统手动重新分配和拆解。

总结:

第一类是重新分配的几块内存,有足够多的内部空间去则表示它所代表者的值。

表达式是三个系统表的原素,保有指向第一类的连接的空间。

提及是手动形成的从表达式到第一类的指针。

Python 动态类别语言

表达式不需要显示声明类别。第一类的类别是内建的。

根据表达式提及的第一类,Python解释器手动跟踪第一类的类别,从而确定类别,所以是动态型。

Python 强类别语言

每个第一类都有统计数据类别,且只全力支持该类别全力支持的操作方式。

标记符:

用作表达式、表达式、模块等的名称。

标记符命名规则:

1.区分大小写:如abc 和 ABC是不同的。

2.第三个字符必须是字母、下划线,其后的字符是:字母、数字、下划线。

3.不能采用关键字。如:if 、or、while等

4.双下线开头的和结尾的名称一般来说有特殊含义,尽量避免这种写法。如__init__是构造表达式。

彻底理解Python中对象、对象与变量引用的关系

参考

^第一类的其本质: https://www.cnblogs.com/yingxiongguixing/p/12163743.html^Python 短字符串的内存池: https://www.cnblogs.com/HC2018/articles/10204262.html^Python的表达式不是容器: https://zhuanlan.zhihu.com/p/39566815^逻辑层内存内部空间结构: https://zhuanlan.zhihu.com/p/115353547

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务