写了这么多年的python,tuple竟然是可变的?

2018年6月10日23:05:41 发表评论 548 阅读

 

1

根据Python对数据类型的定义:"objects are Python's abstraction for data, and all data in a Python program is represented by objects or by relations between objects"。

Python中一切皆对象,包括整数浮点数布尔值。在Java中,这些是“primitive数据类型”,并被视为与“objects”分开。

在Python中并非如此。Python中的每个值都是一个对象,所以不仅

1
<span style="font-size: 15px; font-family: Optima-Regular, PingFangTC-light;">datetime.datetime(2018, 6, 3, 19, 38, 54, 798338)</span>

datetime对象是一个对象,而且整数

1
<span style="font-size: 15px; font-family: Optima-Regular, PingFangTC-light;">69</span>

是一个对象,布尔

1
<span style="font-size: 15px; font-family: Optima-Regular, PingFangTC-light;">True</span>

是一个对象。

所有的Python对象都有三件事:一个,一个类型和一个身份。这有点令人困惑,因为我们经常随便说,例如“值

1
<span style="font-size: 15px; font-family: Optima-Regular, PingFangTC-light;">69</span>

”。


1
2
3
4
5
6
7
<span style="font-size: 14px;"><span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>spam =<span class="Apple-converted-space"> </span><span class="" style="color: #b8d7a3; background-color: rgba(0, 0, 0, 0); display: inline; width: 15px;">69</span>
<span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>spam
<span class="" style="color: #b8d7a3; background-color: rgba(0, 0, 0, 0); display: inline; width: 14px;">69</span>
<span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>type(spam)
&lt;<span class="" style="color: #b8d7a3; background-color: rgba(0, 0, 0, 0); display: inline; width: 94px;"><span class="" style="color: #569cd6; background-color: rgba(0, 0, 0, 0); display: inline; width: 36px;">class</span><span class="Apple-converted-space"> </span>'<span class="" style="color: #dcdcdc; background-color: rgba(0, 0, 0, 0); display: inline; width: 21px;">int</span>'&gt;
&gt;&gt;&gt;<span class="Apple-converted-space"> </span><span class="" style="color: #dcdcdc; background-color: rgba(0, 0, 0, 0); display: inline; width: 14px;">id</span><span class="" style="color: #dcdcdc; background-color: rgba(0, 0, 0, 0); display: inline; width: 43px;">(spam)</span>
4307168128</span></span>

该变量

1
<span style="font-size: 15px; font-family: Optima-Regular, PingFangTC-light;">spam</span>

指的是具有值69,类型

1
<span style="font-size: 15px; font-family: Optima-Regular, PingFangTC-light;">int</span>

和id为

1
<span style="font-size: 15px; font-family: Optima-Regular, PingFangTC-light;">4307168128</span>

。id是一个唯一的整数,在创建对象时创建,并且永远不会改变对象的生命周期。对象的类型也不能改变。只有对象的值可能会改变。

让我们尝试通过在交互式shell中输入以下内容来更改对象的值:


1
2
<span style="font-size: 14px;"><span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;"><span class="" style="letter-spacing: 0px; display: inline; width: 29px;">&gt;&gt;&gt; </span><span style="letter-spacing: 0px; color: #dcdcdc;">spam = </span><span class="" style="letter-spacing: 0px; color: #b8d7a3; display: inline; width: 15px;">69</span>
&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>spam =<span class="Apple-converted-space"> </span><span class="" style="color: #b8d7a3; background-color: rgba(0, 0, 0, 0); display: inline; width: 22px;">666</span></span>

 

可能有的同学就会认为已经将对象的值从

1
<span style="font-size: 15px; font-family: Optima-Regular, PingFangTC-light;">69</span>

改变为666,然而并没有。我们所做的都是将

1
<span style="font-size: 15px; font-family: Optima-Regular, PingFangTC-light;">spam</span>

指向1个新的对象。


1
2
3
4
5
6
<span style="font-size: 14px;"><span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;"><span class="" style="letter-spacing: 0px; display: inline; width: 29px;">&gt;&gt;&gt; </span><span style="letter-spacing: 0px; color: #dcdcdc;">spam = </span><span class="" style="letter-spacing: 0px; color: #b8d7a3; display: inline; width: 15px;">69</span>
&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>id(spam)
<span class="" style="color: #b8d7a3; background-color: rgba(0, 0, 0, 0); display: inline; width: 72px;">4307168128</span>
<span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>spam =<span class="Apple-converted-space"> </span><span class="" style="color: #b8d7a3; background-color: rgba(0, 0, 0, 0); display: inline; width: 22px;">666</span>
<span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>id(spam)
<span class="" style="color: #b8d7a3; background-color: rgba(0, 0, 0, 0); display: inline; width: 72px;">4325801680</span></span>

 

整数(浮点数,布尔值,字符串,字节)是不可变的。另外,列表(字典,集合,数组和字节数组)是可变的。这可能会导致一个常见的Python陷阱:


1
2
3
4
5
6
7
8
9
10
11
<span style="font-size: 14px;"><span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>spam = [<span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 66px;">'miracle'</span>,<span class="Apple-converted-space"> </span><span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 51px;">'young'</span>]
<span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>papapa = spam
<span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>spam
[<span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 65px;">'miracle'</span>,<span class="Apple-converted-space"> </span><span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 51px;">'young'</span>]
<span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>papapa
[<span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 65px;">'miracle'</span>,<span class="Apple-converted-space"> </span><span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 51px;">'young'</span>]
<span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>spam.append(<span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 44px;">'girl'</span>)
<span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>spam
[<span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 65px;">'miracle'</span>,<span class="Apple-converted-space"> </span><span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 51px;">'young'</span>,<span class="Apple-converted-space"> </span><span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 44px;">'girl'</span>]
<span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>papapa
[<span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 65px;">'miracle'</span>,<span class="Apple-converted-space"> </span><span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 51px;">'young'</span>,<span class="Apple-converted-space"> </span><span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 44px;">'girl'</span>]</span>

 

究其原因就是papapaspam同时指向了同一个对象。来看

1
<span style="font-size: 15px; font-family: Optima-Regular, PingFangTC-light;">papapa = spam</span>

这行。创建了引用的副本,而不是对象。

2

关于Python is 和 == 的区别,以后我会单独拿出来说一下的。这里我们先来看几个例子:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<span style="font-size: 14px;"><span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>id(spam) == id(papapa)
<span class="" style="color: #569cd6; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">True</span>
<span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>spam<span class="Apple-converted-space"> </span><span class="" style="color: #569cd6; background-color: rgba(0, 0, 0, 0); display: inline; width: 14px;">is</span><span class="Apple-converted-space"> </span>papapa
<span class="" style="color: #569cd6; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">True</span>
<span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>spam == papapa
<span class="" style="color: #569cd6; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">True</span>
<span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>fxxk = [<span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 66px;">'miracle'</span>,<span class="Apple-converted-space"> </span><span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 51px;">'young'</span>,<span class="Apple-converted-space"> </span><span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 43px;">'girl'</span>]
<span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>spam == fxxk
<span class="" style="color: #569cd6; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">True</span>
<span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>id(fxxk)
<span class="" style="color: #b8d7a3; background-color: rgba(0, 0, 0, 0); display: inline; width: 72px;">4325976648</span>
<span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>spam<span class="Apple-converted-space"> </span><span class="" style="color: #569cd6; background-color: rgba(0, 0, 0, 0); display: inline; width: 14px;">is</span><span class="Apple-converted-space"> </span>fxxk
<span class="" style="color: #569cd6; background-color: rgba(0, 0, 0, 0); display: inline; width: 36px;">False</span>
<span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>id(spam)
<span class="" style="color: #b8d7a3; background-color: rgba(0, 0, 0, 0); display: inline; width: 72px;">4325974216</span></span>

2个不同的变量,他们可以共享同一个,但是永远无法共享同一个对象

3

好了,现在有了上面这些做铺垫,我们终于可以展开tuple到底是mutable or immutable了。从某种意义上说元组是不可变的,因为元组中的对象不能被删除或被新对象所替代。就像

1
<span style="font-size: 15px; font-family: Optima-Regular, PingFangTC-light;">spam=69;spam=666</span>

不改变spam=69中的对象一样; 它用一个全新的对象代替它,666


1
2
3
4
<span style="font-size: 14px;"><span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>spam = [<span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 66px;">'miracle'</span>,<span class="Apple-converted-space"> </span><span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 51px;">'young'</span>, [<span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 44px;">'girl'</span>,<span class="Apple-converted-space"> </span><span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 36px;">'boy'</span>]]
<span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>spam = (<span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 66px;">'miracle'</span>,<span class="Apple-converted-space"> </span><span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 51px;">'young'</span>, [<span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 44px;">'girl'</span>,<span class="Apple-converted-space"> </span><span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 36px;">'boy'</span>])
<span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>id(spam[<span class="" style="color: #b8d7a3; background-color: rgba(0, 0, 0, 0); display: inline; width: 8px;">0</span>]), id(spam[<span class="" style="color: #b8d7a3; background-color: rgba(0, 0, 0, 0); display: inline; width: 8px;">1</span>]), id(spam[<span class="" style="color: #b8d7a3; background-color: rgba(0, 0, 0, 0); display: inline; width: 8px;">2</span>])
(<span class="" style="color: #b8d7a3; background-color: rgba(0, 0, 0, 0); display: inline; width: 72px;">4325825872</span>,<span class="Apple-converted-space"> </span><span class="" style="color: #b8d7a3; background-color: rgba(0, 0, 0, 0); display: inline; width: 72px;">4327743416</span>,<span class="Apple-converted-space"> </span><span class="" style="color: #b8d7a3; background-color: rgba(0, 0, 0, 0); display: inline; width: 73px;">4326146632</span>)</span>

相同的对象将始终存在于这个元组中,并且它们将始终具有相同顺序的相同身份:4325825872和4327743416. 因为元组是不可变的

然而在另一种意义上元组是可变的,因为它们的值可以被改变。


1
2
3
4
5
6
7
8
<span style="font-size: 14px;"><span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>fxxk = (<span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 66px;">'miracle'</span>,<span class="Apple-converted-space"> </span><span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 51px;">'young'</span>, [<span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 44px;">'girl'</span>,<span class="Apple-converted-space"> </span><span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 36px;">'boy'</span>])
<span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>spam == fxxk
<span class="" style="color: #569cd6; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">True</span>
<span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>spam<span class="Apple-converted-space"> </span><span class="" style="color: #569cd6; background-color: rgba(0, 0, 0, 0); display: inline; width: 14px;">is</span><span class="Apple-converted-space"> </span>fxxk
<span class="" style="color: #569cd6; background-color: rgba(0, 0, 0, 0); display: inline; width: 36px;">False</span>
<span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>spam[<span class="" style="color: #b8d7a3; background-color: rgba(0, 0, 0, 0); display: inline; width: 7px;">2</span>].append(<span class="" style="color: #d69d85; background-color: rgba(0, 0, 0, 0); display: inline; width: 36px;">'man'</span>)
<span class="" style="color: #9b9b9b; background-color: rgba(0, 0, 0, 0); display: inline; width: 29px;">&gt;&gt;&gt;<span class="Apple-converted-space"> </span></span>spam == fxxk
<span class="" style="color: #569cd6; background-color: rgba(0, 0, 0, 0); display: inline; width: 36px;">False</span></span>

 

在这个例子中,元组称为通过

1
<span style="font-size: 15px; font-family: Optima-Regular, PingFangTC-light;">spam</span>

1
<span style="font-size: 15px; font-family: Optima-Regular, PingFangTC-light;">fxxk</span>

具有相等的值(根据

1
<span style="font-size: 15px; font-family: Optima-Regular, PingFangTC-light;">==</span>

),但是是不同的对象(根据

1
<span style="font-size: 15px; font-family: Optima-Regular, PingFangTC-light;">is</span>

)。

接着我们改变了spam的值,因为

1
spam

不再等于

1
fxxk

,而我们也没有改变

1
fxxk

的值。所以元组又是可变的

 

- The End -

本篇文章来源于微信公众号: 程序人生

张晔璇

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: