Python彻底搞懂:变量、对象、赋值、引用、拷贝

2022-12-16 0 886

Python3自学讲义:Python中的表达式操作方式

python中的表达式,表达式等详尽导出

秒懂Python 表达式,浅复本,深复本

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

1 Python为静态如前所述词汇

在表达式操作方式时,

类别是在运转操作过程中手动下定决心的,而并非透过标识符新闻稿,没必要性预先新闻稿表达式。

(静态校对类别词汇C++或Java,在采用表达式前,需新闻稿表达式的类别。)

2 表达式和第一类间的亲密关系为提及。

1 表达式

1 第二次表达式时,即建立,后 再度表达式 Sonbhadra 发生改变 表达式的值。

2 表达式名这类是没类别的,类别只存有第一类中,表达式而已提及了第一类。

3 大部份的表达式,要 在采用前 表达式,采用未表达式的表达式会造成严重错误。

2 第一类

1 第一类是有类别的。

2 第一类是重新分配的几块物理地址,来则表示它的值。

3 每两个第一类都具备三个国际标准的颈部重要信息:

类别dealing:标记第一类的类别。

提及计时器:用以下定决心第一类呢展开拆解。

Python第一类二律背反:Id,Type,Value

Id:唯一标记两个第一类

Type:标记第一类的类别

Value:第一类的值

Python彻底搞懂:变量、对象、赋值、引用、拷贝

3 提及

1 在Python中,从表达式到第一类的连接,称为提及。

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

3 赋值操作方式时,手动建立表达式和第一类间的亲密关系,即提及。

表达式和提及

python中表达式语句,

总是建立第一类的提及值,而并非复制第一类。

因此,python表达式更像是指针,而并非数据存储区域。

简单提及:

例1

a = 3

步骤:

建立两个第一类来代表值3。

建立两个表达式a,如果它还没建立的话。

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

如图:

Python彻底搞懂:变量、对象、赋值、引用、拷贝

例2

a = 1 a = python a = 1.2

这里的 表达式a 被多次表达式,

并并非修改的第一类,而是修改的提及,

a指向1,然后修改提及指向 python,

最后指向1.2。

1 和 python 被放在物理地址内,

在没其他表达式提及时,提及计数为0,

这个第一类的物理地址就会手动拆解。

这里也并并非修改表达式 a 的类别,

因为表达式没类别,而已它指向的第一类具备类别,

即第一类颈部重要信息的类别dealing。

共享提及

例1:

a = 3 b = a
Python彻底搞懂:变量、对象、赋值、引用、拷贝

a 指向第一类3,

b = a 表达式操作方式,

b 也指向3。

可以看出,a和b都提及了同两个第一类。

例2:

a = 3 b = a a = spam
Python彻底搞懂:变量、对象、赋值、引用、拷贝

a 重新指向另两个第一类。

== 和 is

== 指值相等。

is 指地址相等,即指提及相等。

a == b

判断 a 第一类的值是否和 b 第一类的值相等。透过Value 值来判断。

a is b

判断 a 第一类是否就是 b 第一类。 透过 Id 来判断。

第一类的数据类别:列表list

表达式相同,提及不同。

例1

lst1 = [1, 2, 3] lst2 = lst1 lst3 = [1, 2, 3] print(lst1,id(lst1)) #查看列表、提及地址 Id()函数 print(lst2,id(lst2)) print(lst3,id(lst3)) lst2[0] = 10 print() print(lst1,id(lst1)) #查看列表、提及地址 Id()函数 print(lst2,id(lst2)) print(lst3,id(lst3))

输出结果

[1, 2, 3] 4434387024

[1, 2, 3] 4434387024

[1, 2, 3] 4478611696

[10, 2, 3] 4434387024

[10, 2, 3] 4434387024

[1, 2, 3] 4478611696

例2

lst1 = [1, 2, 3] lst2 = lst1 lst3 = [1, 2, 3] print(lst1 == lst2) print(lst1 is lst2) print(lst1 == lst3) print(lst1 is lst3)

输出结果

True

True

True

False

总结:

lst1 和 lst2 指向同两个对象。

lst1 和 lst3 不指向同两个第一类(Id不同),lst3 指向另一第一类,

三个第一类而已值(value)相等(==)。

第一类的数据类别:整数int。

表达式相同,则提及相同。

a = 9 b = a c = 9 print(a,id(a)) print(b,id(b)) print(c,id(c)) print() print(a == b) print(a is b) print(a == c) print(a is c)

输出结果

9 4393189392

9 4393189392

9 4393189392

True

True

True

True

a、b、c 指向 同两个第一类。

因为小的整数 和 字符串 被缓存 并复用,

所以 is 指明 a 和 c ,提及一个相同的第一类。

a = 1 a = python

这里的 1 并没被直接拆解,虽然它的计数减一,但是在系统标识符中却被大量提及。

查看提及计数如下 :

import sys print(sys.getrefcount(1))

输出结果:

717

表达式是两个系统表的元素,拥有指向第一类的连接的空间。

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

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

表达式、浅复本、深复本

python中的表达式,表达式等详尽导出

可以说 Python 没表达式,只有提及。

Python 没「表达式」,我们平时所说的表达式其实而已「标签」,是提及。

values = [0, 1, 2] values = [3, 4, 5] values[1] = values
values = [0, 1, 2]

Python 做的事情是首先建立两个列表第一类 [0, 1, 2],然后给它贴上名为 values 的标签。

values = [3, 4, 5]

建立另两个列表第一类 [3, 4, 5],然后把刚才那张名为 values 的标签从前面的 [0, 1, 2] 第一类上撕下来,重新贴到 [3, 4, 5] 这个第一类上。

至始至终,并没两个叫做 values 的列表第一类容器存有。

Python 也没把任何第一类的值复制进 values 去。

操作过程如图所示:

Python彻底搞懂:变量、对象、赋值、引用、拷贝
values[1] = values

把 values 这个标签所提及的列表第一类的第二个元素指向 values 所提及的列表第一类这类。

执行完毕后,values 标签还是指向原来那个第一类,只不过那个第一类的结构发生了变化,

从之前的列表 [0, 1, 2] 变成了 [0, ?, 2],而这个 ? 则是指向那个第一类这类的两个提及。

如图所示:

Python彻底搞懂:变量、对象、赋值、引用、拷贝

得到 [0, [0, 1, 2], 2] 这个第一类,

你不能直接将 values[1] 指向 values 提及的第一类这类,

而是需要吧 [0, 1, 2] 这个第一类「复制」一遍,得到两个新第一类,

再将 values[1] 指向这个复制后的第一类。

Python 里面复制第一类的操作方式因第一类类别而异,复制列表 values 的操作是:

values[:] #生成第一类的复本或者是复制序列,不再是提及和共享表达式,但此法只能顶层复制
values[1] = values[:]

先 dereference 得到 values 所指向的第一类 [0, 1, 2],然后执行 [0, 1, 2][:] 复制操作方式得到两个新的第一类,内容也是 [0, 1, 2],

然后将 values 所指向的列表第一类的第二个元素,指向这个复制二来的列表第一类,最终 values 指向的第一类是 [0, [0, 1, 2], 2]。

操作过程如图所示:

Python彻底搞懂:变量、对象、赋值、引用、拷贝

values[:] 复制操作方式是所谓的「浅复制」(shallow copy),

当列表第一类有嵌套的时候也会造成出乎意料的严重错误。

a = [0, [1, 2], 3] b = a[:] a[0] = 8 a[1][1] = 9

a 为 [8, [1, 9], 3],

b 为 [0, [1, 9], 3]。

b 的第二个元素也被发生改变了。想想是为什么?

Python彻底搞懂:变量、对象、赋值、引用、拷贝

正确的复制嵌套元素的方法是展开「深复制」(deep copy)

import copy a = [0, [1, 2], 3] b = copy.deepcopy(a) a[0] = 8 a[1][1] = 9
Python彻底搞懂:变量、对象、赋值、引用、拷贝

提及 VS 复本:

没限制条件的分片表达式(L[:])能够复制序列,但此法只能浅层复制。

字典 copy 方法,D.copy() 能够复制字典,但此法只能浅层复制。

有些内置函数,例如 list,能够生成复本 list(L)。

copy 国际标准库模块能够生成完整复本:deepcopy 本质上是递归 copy。

对于不可变第一类和可变第一类来说,

浅复制都是复制的提及。

而已因为复制不变第一类和复制不变第一类的提及是等效的

(因为第一类不可变,当发生改变时,会新建第一类重新表达式)。

看起来浅复制只复制不可变第一类(整数,实数,字符串等),

对于可变第一类,

浅复制其实是建立了两个对于该第一类的提及,

也就是说而已给同两个第一类贴上了另两个标签而已。

遗漏待补充:

可变第一类与不可变第一类

Python的第一类分成两类:可变第一类和不可变第一类。

可变第一类是指,第一类的内容是可变的,一般是指提及类别。

不可变的第一类,则表示其内容不可变。对于tuple中的可变第一类也是可以发生改变的。

可变第一类 :list, dict, set

不可变第一类 :int, float, complex, str,bool, tuple, frozenset

Python中的表达式语句,

不会建立第一类的复本,仅是将名称绑定至两个第一类。

对于不可变第一类,通常没什么差别。

不可变第一类 :int, float, complex, str,bool, tuple, frozenset

但处理可变第一类或可变第一类的集合时,

可能需要建立这些第一类的 “真实复本”,

在修改建立的复本时,不发生改变原始的第一类。

可变第一类 :list, dict, set

相关文章

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

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