10.python中的序列
本来说完字符串、数字、布尔值之后,应该要继续讲元祖、列表之类的。但是元祖和列表都属于序列,所以有必要先讲讲python的序列是什么。
首先,序列是是Python中最基本的数据结构。序列中的每个元素都分配一个数字 - 它的位置,或索引,第一个索引是0,第二个索引是1,依此类推。每个索引对应一个元素。
Python包含 6 中内建的序列,包括列表、元组、字符串、Unicode字符串、buffer对象和xrange对象。
对于序列,都可以使用以下操作:
1.索引
2.切片
3.加
4.乘
5.成员检查
6.计算序列的长度
7.取序列中的最大、最小值
1.索引
所谓的索引就是对每个元素进行编号,注意,编号是从0开始的。
我们可用通过索引来取得其对应的元素:
对于字符串:
a = 'scolia' b = a[3] print b print type(b)
注意:对字符串而言,取出的元素依然是字符串类型。
对于元祖:
a = ('scolia', 123, True,(),[]) b = a[0] c = a[1] print b print type(b) print c print type(c)
取出来的元素原来是什么类型就是什么类型,为什么会这样呢,看下面这个例子:
竟然是同一个对象,也就是说变量 l 和变量b 指向了同一个内存空间。
def text(): print 'scolia' a = ('scolia', 123, True, (), text) b = a[4] b()
里面放函数也可以,那么这样呢?
l = [] a = ('scolia', 123, True, (), l) b = a[4] b.append(1) #append()是列表的一个方法,将一个元素添加到列表的最后,对原列表进行操作,但返回值为None print l print b
我们对取出来的元素进行了操作,竟然影响了原列表。
这说明了:
序列其实是一个容器,里面可以放任何的对象,而当我们通过索引去取的时候,取到的原对象。那么我看是不是可以将索引看作是一个特别的变量,它指向的也是内存空间,当然这个说法套到字符串中略显变扭,我们只能假设字符串是将每个字符都存在一个内存空间中,每个字符都是字符串类型,变量取得的是整个字符串,而索引则是每个字符的变量。我们看看这个假设的结果如何
a = 'abcdabcd' print id(a[0]),id(a[4])
好像假设成立?
那这样呢:
a = 'abcdabcd' b = 'a' print id(a[0]),id(a[4]),id(b)
看到这里你是不是明白了什么。
字符串是字符对象的引用的集合,所以我们使用英文的时候是不是最多只有创建26个字母,然后字符串只要重复引用就可以了。其他字符也同理。
我们对于序列的了解就更深了一步。
2.切片
所谓切片就是一次拿出多个对象,而索引一次只能拿出一个对象。
a = ('scolia', 123, True) b = a[0:2] print b
返回的依然是一个元祖,这里要注意一个问题,那就是 a[2] 明明是 True 才对,但结果我们并没有取到,说明切片是不包括后界限的索引的。
另外,我可以只写其中的一个:
a = ('scolia', 123, True) b = a[1:] print b
表示从某索引开始(包括),取到结束。
a = ('scolia', 123, True) b = a[:2] print b
表示从最开始,取到结束的索引(不包括)。
另外,还可以使用负数:
a = ('scolia', 123, True) b = a[-2:] print b
正数表示索引是从左向右计算的,而负数则表示倒数,如-1就表示倒数第一个。
但是,取对象的方向还是从左到右的,这里要注意下。
另外:
a = ('scolia', 123, True) b = a[-3:-1] print b
此时的后索引就成了-1了,在使用负数的使用要注意。所以所谓的后索引就是最后一个元素的索引,而不包括后索引就是不包括那个元素,只单纯作为分界线。
但如果我这样写呢:
a = ('scolia', 123, True) b = a[-1:-3] print b
开头的索引在结束的索引的右边,是不是就可以倒过来取了呢?
答案是:
不可以,得到空的。看来一定要从左向右取对象。
还有,当我给的索引超出了呢?
a = ('scolia', 123, True) b = a[0:100] print b
python能自动处理索引超出的问题,这也是python优雅的所在。
但是要注意:
a = ('scolia', 123, True) b = a[10:100] print b
这样就取不到了。
最后,还有一个小技巧,虽然切片得到的是一个元祖,但能找到我们切片得到了几个元素,如果此时我用多个变量去承接呢?
a = ('scolia', 123, True) b,c,d = a[:] #这里能得到原序列,此外还涉及到深浅拷贝的问题,以后再来解释 print b print c print d
这样我能得到独立的对象了。
最后,在来讲讲切片中的步进,先看代码:
所谓步进就是要走几步取一个,本来在没设置步进的时候,应该取到(1,2,3)的.
而这里的步进表示走2步取一个。1->2第一步,2->3第二步,所以从1开始走2步就是3了。
在不进行步进设置的时候默认为1,也就是每一个都取到。
3.加
对序列进行加法运算,将返回一个新的对象。
a = ('scolia', 123, True) b = ('good', 456) c = a + b print a print b print c
并没有影响到原序列。
那么不同类型的序列相加呢?
a = ('scolia', 123, True) b = ['good', 456] c = a + b print a print b print c
不行。
列表的相加也是一样的,这里不重复举例。
另外,和字符串的+号拼接也是一样的。
4.乘
乘法和加法类似,只是几个一样的序列相加而已,这点和数学的乘法一样。
a = ('scolia', 123, True) b = a*2 print a print b
同样不影响原序列
5.成员检查
这里主要是 in 和 not in 运算符的使用。
b = 3000 print id(b) a = ('scolia', 3000, True) print b in a print id(a[1]), id(b)
这里的结果很奇怪,如果还记得python中的缓存池(上篇有说过)的话,不是说数字只在 -5~257 才会有缓存行为吗?看来python内部针对这种情况特别做了优化,达到了节省内存的效果。
就算赋值行为在下面也一样。
a = ('scolia', 3000, True) b = 3000 print b in a print id(a[1]), id(b)
看来在变量赋值时还有隐藏行为,python会检查元祖和列表中是否已经有一样的对象了,若有则赋值时不重新创建,而是重复引用。
6.元素长度计算
其实是 len() 内置函数的调用,该函数会返回容器中元素的数量。
a = ('scolia', 3000, True) print len(a)
计算是从1开始的,和索引不同,要注意区分。
还有,虽然这里是写在序列之中,但是这个方法对字典也适用,而字典算是特殊的一种'序列'。
a = {'a':1,'b':2} print len(a)
7.取序列中的最大、最小值
这里其实是内置函数 max() 和 max() 的使用,其会返回序列中的最大、最小值。
关于不同数据的比较请参照:戳这里
或者参考我之前关于python的数字的博文。
a = ('scolia', 3000, True) print max(a)
关于序列的内容暂时写这么多,以后有需要的话会继续补充。