前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >2.13 Python 赋值机制

2.13 Python 赋值机制

作者头像
py3study
发布2020-01-10 12:13:17
5770
发布2020-01-10 12:13:17
举报
文章被收录于专栏:python3

先看一个例子:

In [1]:

代码语言:javascript
复制
x = [1, 2, 3]
y = x
x[1] = 100
print y



[1, 100, 3]

改变变量x的值,变量y的值也随着改变,这与Python内部的赋值机制有关。

简单类型

先来看这一段代码在Python中的执行过程。

代码语言:javascript
复制
x = 500
y = x
y = 'foo'
  • x = 500

Python分配了一个 PyInt 大小的内存 pos1 用来储存对象 500 ,然后,Python在命名空间中让变量 x 指向了这一块内存,注意,整数是不可变类型,所以这块内存的内容是不可变的。

内存 命名空间 pos1 : PyInt(500) (不可变) x : pos1

  • y = x

Python并没有使用新的内存来储存变量 y 的值,而是在命名空间中,让变量 y 与变量 x 指向了同一块内存空间。

内存 命名空间 pos1 : PyInt(500) (不可变) x : pos1“y : pos1

  • y = ‘foo’

Python此时分配一个 PyStr 大小的内存 pos2 来储存对象 foo ,然后改变变量 y 所指的对象。

内存 命名空间 pos1 : PyInt(500) (不可变)pos2 : PyStr(‘foo’) (不可变) x : pos1“y : pos2

对这一过程进行验证,可以使用 id 函数。

代码语言:javascript
复制
id(x)

返回变量 x 的内存地址。

In [2]:

代码语言:javascript
复制
x = 500
id(x)

Out[2]:

代码语言:javascript
复制
48220272L

In [3]:

代码语言:javascript
复制
y = x
id(y)

Out[3]:

代码语言:javascript
复制
48220272L

也可以使用 is 来判断是不是指向同一个事物:

In [4]:

代码语言:javascript
复制
x is y

Out[4]:

代码语言:javascript
复制
True

现在 y 指向另一块内存:

In [5]:

代码语言:javascript
复制
y = 'foo'
id(y)

Out[5]:

代码语言:javascript
复制
39148320L

In [6]:

代码语言:javascript
复制
x is y

Out[6]:

代码语言:javascript
复制
False

Python会为每个出现的对象进行赋值,哪怕它们的值是一样的,例如:

In [7]:

代码语言:javascript
复制
x = 500
id(x)

Out[7]:

代码语言:javascript
复制
48220296L

In [8]:

代码语言:javascript
复制
y = 500
id(y)

Out[8]:

代码语言:javascript
复制
48220224L

In [9]:

代码语言:javascript
复制
x is y

Out[9]:

代码语言:javascript
复制
False

不过,为了提高内存利用效率,对于一些简单的对象,如一些数值较小的int对象,Python采用了重用对象内存的办法:

In [10]:

代码语言:javascript
复制
x = 2
id(x)

Out[10]:

代码语言:javascript
复制
6579504L

In [11]:

代码语言:javascript
复制
y = 2
id(y)

Out[11]:

代码语言:javascript
复制
6579504L

In [12]:

代码语言:javascript
复制
x is y

Out[12]:

代码语言:javascript
复制
True

容器类型

现在来看另一段代码:

代码语言:javascript
复制
x = [500, 501, 502]
y = x
y[1] = 600
y = [700, 800]
  • x = [500, 501, 502]

Python为3个PyInt分配内存 pos1 , pos2 , pos3 (不可变),然后为列表分配一段内存 pos4 ,它包含3个位置,分别指向这3个内存,最后再让变量 x 指向这个列表。

内存 命名空间 pos1 : PyInt(500) (不可变) pos2 : PyInt(501) (不可变) pos3 : PyInt(502) (不可变) pos4 : PyList(pos1, pos2, pos3) (可变) x : pos4

  • y = x

并没有创建新的对象,只需要将 y 指向 pos4 即可。

内存 命名空间 pos1 : PyInt(500) (不可变) pos2 : PyInt(501) (不可变) pos3 : PyInt(502) (不可变) pos4 : PyList(pos1, pos2, pos3) (可变) x : pos4“y : pos4

  • y[1] = 600

原来 y[1] 这个位置指向的是 pos2 ,由于不能修改 pos2 的值,所以首先为 600 分配新内存 pos5 。

再把 y[1] 指向的位置修改为 pos5 。此时,由于 pos2 位置的对象已经没有用了,Python会自动调用垃圾处理机制将它回收。

内存 命名空间 pos1 : PyInt(500) (不可变) pos2 : 垃圾回收 pos3 : PyInt(502) (不可变) pos4 : PyList(pos1, pos5, pos3) (可变)pos5 : PyInt(600) (不可变) x : pos4“y : pos4

  • y = [700, 800]

首先创建这个列表,然后将变量 y 指向它。

内存 命名空间 pos1 : PyInt(500) (不可变) pos3 : PyInt(502) (不可变) pos4 : PyList(pos1, pos5, pos3) (可变)pos5 : PyInt(600) (不可变) pos6 : PyInt(700) (不可变)pos7 : PyInt(800) (不可变)pos8 : PyList(pos6, pos7) (可变) x : pos4 y : pos8

对这一过程进行验证:

In [13]:

代码语言:javascript
复制
x = [500, 501, 502]
print id(x[0])
print id(x[1])
print id(x[2])
print id(x)



48220224
48220248
48220200
54993032

赋值,id(y) 与 id(x) 相同。

In [14]:

代码语言:javascript
复制
y = x
print id(y)



54993032

In [15]:

代码语言:javascript
复制
x is y

Out[15]:

代码语言:javascript
复制
True

修改 y[1] ,id(y) 并不改变。

In [16]:

代码语言:javascript
复制
y[1] = 600
print id(y)



54993032

id(x[1]) 和 id(y[1]) 的值改变了。

In [17]:

代码语言:javascript
复制
print id(x[1])
print id(y[1])



48220272
48220272

更改 y 的值,id(y) 的值改变

In [18]:

代码语言:javascript
复制
y = [700, 800]
print id(y)
print id(x)

54995272
54993032
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/08/18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档