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)


  关于序列的内容暂时写这么多,以后有需要的话会继续补充。

 

posted @ 2016-05-28 00:57  scolia  阅读(7141)  评论(0编辑  收藏  举报