第七章 python3 元组tuple
元组tuple是一个比较常用的不可变序列;都说元组tuple和列表list很类似,不同之处在于元组一旦创建就不可改变。
元组中的元素真的不能再修改吗?元组和列表它们到底都有什么样的区别呢?下面我们就去一探究竟:
首先是元组的定义,它是用小括号( )来创建的,元素item间用逗号(,)隔开,实例代码:
根据运行结果我们不难看出,元组中的元素item也可以是不同类型的对象,这点和列表list是一样的;定义上列表list用的是中括号[];二者的元素之间都使用逗号(,)隔开的。
当元组中只有一个元素时该如何定义,实例代码:
从上面的结果我们得出这样一个结论:当元组tuple内只有一个元素时,元素后面必须要加上一个逗号(,);否则Python解释器会把小括号当作运算符来计算,其结果就是一个整数5;为了消除这种歧义,Python要求在定义只有一个元素的元组时,元素的后面必须加上一个逗号(,);这点和列表list是不相同的。
1、元组tuple 索引和切片
元组tuple的索引和切片方法与列表list的索引和切片方法基本是一样的;都遵循 [头下标:尾下标)“左闭右开”原则,也叫“包左不包右”原则:
我们修改下其中一个元素:
呃?!怎么还报错了呢?提示tuple对象不支持元素赋值。
哦,这就是我们常说的“元组tuple一旦定义就不可改变了”。
2、元组tuple 嵌套
实例代码:
我们试着把元组中的'Java'改成'Go',实例代码:
不说是元组一旦定义后就不能改变了吗,怎么又可以改变了呢?这都把人搞糊涂了!细心的朋友就会发现,被改变的元素是一个list类型,因为列表是一个可变类型;
说的没错,是这样子的。如果元组中的某个元素是一个不可改变的类型对象,如:常量,字符串等,那么在修改这些不可变的元组的元素时就会报错;如果元组中的某个元素是一个可变对象,如:列表list等,这时候是可以修改的,也不会报错。
表面上看,tuple的元素确实变了,但其实变的不是tuple的元素,而是list的元素。
我们再来一例,继续剖析:
前两次del() 都报错了,说明元组一旦创建后元素是不能被删除的;其实字符串也有这个属性的,一旦创建好之后,里面的单字符串是不能被删除的。
后面三次del() 删除掉的是可变元素list中的子元素,当list可变元素中的子元素被全部删除掉(空列表[])后,如果再继续删除就会报TypeError错。
上面实例使用id()一直在“监控”元组最后一个元素的内存地址变化,发现无论怎么删除,它的内存地址一直保持不变。
如果我们对最后一个可变元素赋值会怎么样?实例代码:
上面报IndexError下标越界异常是因为tuple_org[-1]这时候已经是一个空列表[ ]了,里面是没有任何元素的,[0]代表第1位元素的位置,故而报错;
上面实例的整个过程,无论怎么给最后一个元素赋值都会报错:tuple_org[-1],你是去了趟泰国吗?变性了?
言归正传,结合上面的实例和id()函数的输出结果,我们分析下:
元组tuple它是一个不可变序列,所谓的元组“不可变”是指元组中的每个元素它的内存指向永远不变。所有的不可变序列在第一次定义后“内存指向”就不可以再修改了,它包含了对其他对象的引用,这些引用对象有可能是可变的或可修改的;
虽说元组中的元素值不允许修改的,但我们可以用 = 对元组进行拼接,
实例代码:
经过 += 追加操作之后,a元组的内存地址发生了变化,因为它给新进来的元素重新分配了内存地址。
3、Python内置函数
len()求序列的元素个数,sorted()对序列进行排序,实例代码:
注意:sorted()内置函数对元组排序时,返回的并不是一个新的元组对象,而是一个排好序的列表list对象,而元组本身并没有任何变化;
把元组转换为列表,实例代码:
虽然元组中的元素值是不允许删除的,但我们可以使用del语句来删除整个元组,实例代码:
对了,元组没有自己的方法,而列表是有自己的操作方法的。
4、总结一下
元组本身所指向的内存,实际上保存的是元组内数据的内存地址集合,元组一旦建立,这个内存地址集合就不能修改和删除了。一旦集合内的地址发生改变,就必须重新分配元组空间保存新的内存地址集。
元组还有一个升级版本:具名元组 namedtuple,它是collections模块中的函数对象。
具名元组会放到后续的面向对象中给大家介绍一下,因为它需要结合类对象来使用才能说的明白些。感兴趣的朋友可以自己先去了解一下。
看完上面的这些实例和分析,大家对元组这种不可变序列的理解是不是更深一层了呢。