014、Python 赋值机制
本文最后更新于 67 天前,其中的信息可能已经过时,如有错误请发送邮件到wuxianglongblog@163.com

Python 赋值机制

先看一个例子:

x = [1, 2, 3]
y = x
x[1] = 100
y
[1, 100, 3]

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

简单类型的赋值机制

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

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) (不可变) x : pos1
pos2 : PyStr('foo') (不可变) y : pos2

逻辑验证

对这一过程进行验证,可以使用 id() 函数,该函数返回某个变量在内存中的地址,内存地址一样的变量通常是同一个变量。

x = 500
id(x)
4558905936
y = x
id(y)
4558905936

内存地址一样,说明x和y是同一个对象。也可以用关键字is判断:

x is y
True
y = 'foo'
id(y)
4533836208

y的内存变化了,但是x的内存没有变化:

id(x)
4558905936

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

z = 500
id(z)
4558906096
z is x
False

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

x = 2
id(x)
4507801936
y = 2
id(y)
4507801936
x is y
True

容器类型的赋值机制

看另一段代码:

现在来看另一段代码:

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) (不可变) x : pos4
pos2 : PyInt(501) (不可变)
pos3 : PyInt(502) (不可变)
pos4 : PyList(pos1, pos2, pos3) (可变)
  • 第二句y = x

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

内存 命名空间
pos1 : PyInt(500) (不可变) x : pos4
pos2 : PyInt(501) (不可变) y : pos4
pos3 : PyInt(502) (不可变)
pos4 : PyList(pos1, pos2, pos3) (可变)
  • 第三句y[1] = 600

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

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

内存 命名空间
pos1 : PyInt(500) (不可变) x : pos4
pos2 : 垃圾回收
pos3 : PyInt(502) (不可变)
pos4 : PyList(pos1, pos5, pos3) (可变)
pos5 : PyInt(600) (不可变) y : pos4
  • 第四句y = [700, 800]

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

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

逻辑验证

x = [500, 501, 502]
id(x)
4558869696
id(x[0]), id(x[1]), id(x[2])
(4558906992, 4558906960, 4558906288)

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

y = x
id(y)
4558869696
y is x
True

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

y[1] = 600
id(y)
4558869696

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

id(x[1])
4558906608
id(y[1])
4558906608

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

y = [700, 800]
id(y)
4558861888

id(x) 的值不变:

id(x)
4558869696
谨此笔记,记录过往。凭君阅览,如能收益,莫大奢望。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇