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

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中的每个值都是一个对象,所以不仅datetime.datetime(2018, 6, 3, 19, 38, 54, 798338)datetime对象是一个对象,而且整数69是一个对象,布尔True是一个对象。

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

>>> spam = 69
>>> spam
69
>>> type(spam)
<class 'int'>
>>> id(spam)
4307168128

该变量spam指的是具有值69,类型int和id为4307168128。id是一个唯一的整数,在创建对象时创建,并且永远不会改变对象的生命周期。对象的类型也不能改变。只有对象的值可能会改变。

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

>>> spam = 69
>>> spam = 666

可能有的同学就会认为已经将对象的值从69改变为666,然而并没有。我们所做的都是将spam指向1个新的对象。

>>> spam = 69
>>> id(spam)
4307168128
>>> spam = 666
>>> id(spam)
4325801680

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

>>> spam = ['miracle', 'young']
>>> papapa = spam
>>> spam
['miracle', 'young']
>>> papapa
['miracle', 'young']
>>> spam.append('girl')
>>> spam
['miracle', 'young', 'girl']
>>> papapa
['miracle', 'young', 'girl']

究其原因就是papapa和spam同时指向了同一个对象。来看papapa = spam这行。创建了引用的副本,而不是对象。

2

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

>>> id(spam) == id(papapa)
True
>>> spam is papapa
True
>>> spam == papapa
True
>>> fxxk = ['miracle', 'young', 'girl']
>>> spam == fxxk
True
>>> id(fxxk)
4325976648
>>> spam is fxxk
False
>>> id(spam)
4325974216

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

3

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

>>> spam = ['miracle', 'young', ['girl', 'boy']]
>>> spam = ('miracle', 'young', ['girl', 'boy'])
>>> id(spam[0]), id(spam[1]), id(spam[2])
(4325825872, 4327743416, 4326146632)

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

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

>>> fxxk = ('miracle', 'young', ['girl', 'boy'])
>>> spam == fxxk
True
>>> spam is fxxk
False
>>> spam[2].append('man')
>>> spam == fxxk
False

在这个例子中,元组称为通过spamfxxk具有相等的值(根据==),但是是不同的对象(根据is)。

接着我们改变了spam的值,因为spam不再等于fxxk,而我们也没有改变fxxk的值。所以元组又是可变的

如果你对今天的内容还感兴趣的话,何不点个赞再走呢?如果感兴趣到想赞赏我,就不要犹豫啦~

原文发布于微信公众号 - 猿媛牧场(xpchuiit)

原文发表时间:2018-06-04

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏C/C++基础

Google C++编程风格指南(四)之类的相关规范

类是C++中基本的代码单元,自然被广泛使用。本节列举了在写一个类时要做什么、不要做什么。

952
来自专栏CodingToDie

Python学习(四):dict,set和关键字

第4 章 dict,set和关键字 Table of Contents dict set 再谈遍历 标识符(Identifiers) 关键字 判断、循环 函数、...

3504
来自专栏玄魂工作室

Python黑帽编程2.5 函数

写了几节的基础知识,真心感觉有点力不从心。这块的内容说实话,看文档是最好的方式,本人的写作水平,真的是找不出更好的写法,头疼。简单带过和没写一样,写详细了和本系...

3084
来自专栏有趣的Python

慕课网-c语言入门-学习笔记

个人整理,学习自用。课程内容by慕课网。 c语言入门 C语言一经出现就以其功能丰富、表达能力强、灵活方便、应用面广等特点迅速在全世界普及和推广。C语言不但执行效...

7146
来自专栏HTML5学堂

JS实战开发经验!函数多参数传参技巧

HTML5学堂-码匠:掌握JavaScript代码的你,一定编写封装过函数,为了提升函数的控制性,必不可少的就是参数,必选可选的一大堆参数罗列出来,函数调用貌似...

3745
来自专栏专注 Java 基础分享

Java 内部类的意义及应用

众所周知,我们的 C++ 程序语言是多继承制的,而多继承明显的好处就是,相对而言只需要写较少的代码即可完成一个类的定义,因为我们可以通过继承其它类来获取别人的实...

3194
来自专栏武军超python专栏

2018年7月27日python面向对象中的继承

函数式开发和面向对象的开发的区别: 函数式开发在每次调用的时候都需要给参数传参, 而面向对象的开发,可以把函数定义在类型里面叫做方法,只需要在创建对象的时候...

863
来自专栏机器学习从入门到成神

《你不知道的JavaScript》读书笔记(一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_35512245/articl...

661
来自专栏个人随笔

房上的猫:楼主错题:解析

本题考查的是对java中数组的相关知识, 数组一旦定义就不能改变大小了;数组中存放的都是同一类型的数据;数组的下标是从0开始的,也就是说下标为0的位置存放的是第...

39211
来自专栏Python中文社区

Python内嵌作用域与函数闭包

前情回顾,上一节我们介绍了变量的LEGB索引机制:对一个变量,首先在本地(函数内)查找;之后查找嵌套函数的本地作用域,然后再是查找当前的全局作用域。

1234

扫码关注云+社区