(二)序列构成的数组

1、序列类型包括两类,容器序列和扁平序列

    (1)容器序列:list、tuple 和 collections.deque 这些序列能存放不同类型的数据

    (2)扁平序列:str、bytes、bytearray、memoryview 和 array.array,这类序列只能容纳一种类型。
2、也可分为可变类型和不可变类型

    (1)可变序列:list、bytearray、array.array、collections.deque 和 memoryview。
    (2)不可变序列:tuple、str 和 bytes。
3、列表推导(list comprehension)

     原则:只用列表推导创建新的列表,列表推导代码超过两行,考虑用for循环重写。

   

4、列表推导不会再有变量泄露的问题

      列表推导在python2和python3中有所不同

    

    python3

     

5、列表推导同filter和map的比较

      filter和map合起来能做的事情,列表推导同样可以做,并且更容易理解,效率上后者并不一定比前者慢。

     

6、列表推导例子(笛卡尔积)

    (1) 这里得到的结果是先以颜色排列,再以尺码排列

 (2) 这里两个循环的嵌套关系和上面列表推导中 for 从句的先后顺序一样

    (3)如果想依照先尺码后颜色的顺序来排列,只需要调整从句的顺序

    (4)列表推导的作用只有一个:生成列表。如果想生成其他类型的序列,生成器表达式就派上了用场

    

 7、生成器表达式

       (1)生成器表达式的语法跟列表推导差不多,只不过把方括号换成圆括号而已。
       (2) 虽然也可以用列表推导来初始化元组、数组或其他序列类型,但是生成器表达式是更好的
        选择。这是因为生成器表达式背后遵守了迭代器协议,可以逐个地产出元素,而不是先建
        立一个完整的列表,然后再把这个列表传递到某个构造函数里。前面那种方式显然能够节
        省内存。


8、元组

       元组不仅可以作为不可变列表,还可以作为没有字段名的记录。

      8.1  元组和记录

             元组中的元素,不仅记录了数据,还记录了数据的位置,拆包可以让元组完美地被当作记录来使用。

             8.1.1 元组拆包

                     1、元组拆包可以用到任意可迭代对象上

      2、用*运算符可把一个可迭代对象拆开作为函数的参数        

>>> divmod(20, 8)
(2, 4)
>>> t = (20, 8)
>>> divmod(*t)  

 

       3、函数返回时,用元组可以返回多个值

                    4、用*处理剩下的元素      

>>> a, *body, c, d = range(5)
>>> a, body, c, d
(0, [1, 2], 3, 4)
>>> *head, b, c, d = range(5)
>>> head, b, c, d
([0, 1], 2, 3, 4)

 

                  5、Python 3 之前,元组可以作为形参放在函数声明中,例如 def fn(a, (b,c), d):。然而 Python 3 不再支持这种格式 。
          8.1.2   具名元组

                   有时需要给记录中的字段命名,namedtuple函数可解决这个问题。collections.namedtuple 是一个工厂函数,它可以用来构建一个带字段名的元组和一个有名字的类 。
                    

 

         具名元组的其他属性

                    

      8.2 不可变列表

           除了记录,元组还可以当作不可变列表。

           除了跟增减元素相关的方法外,元组支持列表的所有方法。

     8.3  切片

            1、对对象进行切片

                  

          2、多维切片和省略

    [] 运算符里还可以使用以逗号分开的多个索引或者是切片,外部库 NumPy 里就用到了这个特性,二维的 numpy.ndarray 就可以用 a[i, j] 这种形式来获取,抑或是用 a[m:n, k:l]
          的方式来得到二维切片。 

             NumPy 中, ... 用作多维数组切片的快捷方式。如果 是四维数组,那么 x[i, ...] 就是 x[i, :, :, :] 的缩写。 
          3、给切片赋值

                

         4、序列的拼接:使用+和*

   

            注意:

                   

          例如:

               

        5、序列的增量赋值: += 和 *=

             对于可变是象, +=实现了就地加法,对于不可变对象,则会创建一个新对象。

             

      6、一个关于+=的谜题

           

       8.4、排序

                list.sort就地排序,返回值None;sorted则会创建一个新的列表作为返回值。两个方法都有两个参数,reverse(True则为降序)和key(只有一个参数的函数)

     

      8.5  用bisect来管理已排序的序列

             已排序的序列可以快速用来查找和插入,bisect使用二分查找算法。

             bisect模块包含两个主要函数,bisect和insort,两个函数都是利用二分查找算法在有序序列中查找或插入元素。

             bisect(haystack, needle) haystack(干草垛)里搜索 needle(针)的位置 。

             

        insort(seq, item) 把变量 item 插入到序列 seq 中,并能保持 seq 的升序顺序

9、可替换列表的数据结构

      当要存放100万个float数据时,数组(array)比列表效率要高;当包含操作使用较多时,用集合(set)更适合。

      (1)数组

                如果只包含数字,array比list更高效,array支持list的所有操作,此外,数组还提供从文件读取和存入文件的更快的方法(.frombytes和.tofile)

                

 

              Python 3.4 开始,数组类型不再支持诸如 list.sort() 这种就地排序方法。要给数组排序的话,得用 sorted 函数新建一个数组:
                     a = array.array(a.typecode, sorted(a))
           想要在不打乱次序的情况下为数组添加新的元素, bisect.insort 还是能派上用场 
         (2)内存视图(memoryview)

                memoryview是一个内置类,它可以在不复制内容的情况下,操作同一个数组的不同切片。

                memoryview.cast 的概念跟数组模块类似,能用不同的方式读写同一块内存数据,而且内容字节不会随意移动。 

 

 

            (3)numpy

                

 

10、另一种可替代列表的数据结构:队列

        使用append和pop方法,可以把列表当作栈或队列来使用,但删除或增加第一个元素的操作很耗时(移动元素)。

        collections.deque 类(双向队列)是一个线程安全、可以快速从两端添加或者删除元素的数据类型。而且如果想要有一种数据类型来存放“最近用到的几个元素”, deque 也是一个很好的选择。 
        新建双向队列时,可以指 定队列的大小,当队列满员时,可以从反向端删除过期元素,然后在尾端添加新的元素。
        

            双向队列从中间删除元素会慢一些,append popleft 都是原子操作,也就说是 deque 可以在多线程程序中安全地当作先进先出的栈使用,而使用者不需要担心资源锁的问题 。

 

posted @ 2018-10-30 17:34  牧马人夏峥  阅读(428)  评论(0编辑  收藏  举报