序列构成的数组

内置序列类型概览

1332522-20180211102225420-1464092527.png

列表推导和生成器表达式

In [20]: {s for s in "sstringg"}  # 集合推导
Out[20]: {'g', 'i', 'n', 'r', 's', 't'}

In [25]: [s for s in "string" if s != "i"]
Out[25]: ['s', 't', 'r', 'n', 'g']

In [27]: {s:i for i, s in enumerate("string")}
Out[27]: {'g': 5, 'i': 3, 'n': 4, 'r': 2, 's': 0, 't': 1}

In [28]: (s for s in "string" if s != "i")
Out[28]: <generator object <genexpr> at 0x7fd844195fc0>

In [29]: list(s for s in "string" if s != "i")  # 这里只需要一个括号
Out[29]: ['s', 't', 'r', 'n', 'g']

元组

元组拆包

In [30]: a, b, *rest = range(5)

In [31]: a, b, *rest  # rest均是一个list,无论有没有值
Out[31]: (0, 1, 2, 3, 4)

In [32]: a, b, *rest = range(3)

In [33]: a, b, *rest
Out[33]: (0, 1, 2)

In [34]: rest
Out[34]: [2]

In [35]: a, b, *rest = range(2)

In [36]: rest
Out[36]: []

具名元组

collections.namedtuple 是一个工厂函数,它可以用来构建一个带字段名的元组和一个有名字的类——这个带名字的类对调试程序有很大帮助。

In [1]: from collections import namedtuple

In [2]: City = namedtuple('City', 'name coutry population coordinates')

In [3]: tokyo = City('Tokyo', 'JP', 36.933, (35.689722, 139.691667))

In [4]: tokyo.name  # 可以通过属性,以及索引来获取值.
Out[4]: 'Tokyo'

In [5]: tokyo["name"]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-5-b68fdbfa4b27> in <module>()
----> 1 tokyo["name"]

TypeError: tuple indices must be integers or slices, not str

In [6]: tokyo[1]
Out[6]: 'JP'

In [7]: City._fields # 包含这个类所有字段名称的元组
Out[7]: ('name', 'coutry', 'population', 'coordinates')

In [8]: LatLong = namedtuple('LatLong', 'lat long')

In [9]: City = namedtuple('City', 'name coutry population coordinates')

In [10]: delhi_data = ('Delhi NCR', 'IN', 21.935, LatLong(28.613889, 77.208889))

In [11]: delhi = City._make(delhi_data)  # 接受一个可迭代对象来生成这个类的一个实例,等于City(*delhi_data)

In [12]: delhi._asdict()  # 具名元组以 collections.OrderedDict 的形式返回
Out[12]: 
OrderedDict([('name', 'Delhi NCR'),
             ('coutry', 'IN'),
             ('population', 21.935),
             ('coordinates', LatLong(lat=28.613889, long=77.208889))])

In [13]: for key, value in delhi._asdict().items():
    ...:     print(key + ':', value)
    ...:     
name: Delhi NCR
coutry: IN
population: 21.935
coordinates: LatLong(lat=28.613889, long=77.208889)
方法 列表 元组  说明
s.__add__(s2)s + s2,拼接
s.__iadd__(s2)s += s2,就地拼接
s.append(e)在尾部添加一个新元素
s.clear()删除所有元素
s.__contains__(e)s 是否包含 e
s.copy()列表的浅复制
s.count(e)e 在 s 中出现的次数
s.__delitem__(p)把位于 p 的元素删除
s.extend(it)把可迭代对象 it 追加给 s
s.__getitem__(p)s[p],获取位置 p 的元素
s.__getnewargs__()在 pickle 中支持更加优化的序列化
s.index(e)在 s 中找到元素 e 第一次出现的位置
s.insert(p, e)在位置 p 之前插入元素e
s.__iter__()获取 s 的迭代器
s.__len__()len(s),元素的数量
s.__mul__(n)s * n, n 个 s 的重复拼接
s.__imul__(n)s *= n,就地重复拼接
s.__rmul__(n)n * s,反向拼接 *
s.pop([p])删除最后或者是(可选的)位于 p 的元素,并返回它的值
s.remove(e)删除 s 中的第一次出现的 e
s.reverse()就地把 s 的元素倒序排列
s.__reversed__()返回 s 的倒序迭代器
s.__setitem__(p, e)s[p] = e,把元素 e放在位置p,替代已经在那个位置的元素
s.sort([key],[reverse])就地对s中的元素进行排序,可选的参数有键(key)和是否倒序( reverse)

对序列使用+和*

In [14]: board = [['_'] * 3 for i in range(3)]

In [15]: board
Out[15]: [['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]

In [16]: board[1][2]
Out[16]: '_'

In [17]: board[1][2] = 'X'

In [18]: board
Out[18]: [['_', '_', '_'], ['_', '_', 'X'], ['_', '_', '_']]

上面的代码等价于:

In [23]: def f():
    ...:     board = []
    ...:     for i in range(3):
    ...:         row = ['_'] * 3
    ...:         board.append(row)

而下面的代码会出现预想不到的结果:

In [19]: weird_board = [['_'] * 3] * 3

In [20]: weird_board
Out[20]: [['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]

In [21]: weird_board[1][2] = 'X'

In [22]: weird_board
Out[22]: [['_', '_', 'X'], ['_', '_', 'X'], ['_', '_', 'X']]

等价于:

row=['_'] * 3
board = []
for i in range(3):
    board.append(row)

序列的增量赋值

变量名会不会被关联到新的对象,完全取决于这个类型有没有实现 __iadd__ 这个方法.

什么意思?对于

a += b
  • 如果 a 实现了 __iadd__方法,就会调用这个方法。同时对可变序列(例如list、 bytearray 和 array.array)来说, a 会就地改动,就像调用了a.extend(b)一样。
  • 如果 a 没有实现__iadd__ 的话, a += b 这个表达式的效果就变得跟a = a+ b 一样了:首先计算 a + b,得到一个新的对象,然后赋值给 a。
  • 也就是说,在这个表达式中,变量名会不会被关联到新的对象,完全取决于这个类型有没有实现__iadd__(类是的其他方法,__imul__)这个方法。

对于元组里的可变列表进行+=操作

In [25]: t = (1, 2, [30, 40])

In [26]: t[2] += [50, 60]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-26-d877fb0e9d36> in <module>()
----> 1 t[2] += [50, 60]

TypeError: 'tuple' object does not support item assignment

In [27]: t
Out[27]: (1, 2, [30, 40, 50, 60])

得到的结论是:

  • 会改变
  • 并且会抛出异常
  • 增量赋值不是一个原子操作

list.sort方法和内置函数sorted

  • list.sort 方法会就地排序列表,也就是说不会把原列表复制一份。这也是这个方法的返回值是 None 的原因,提醒你本方法不会新建一个列表。
  • list.sort 相反的是内置函数 sorted,它会新建一个列表作为返回值。

两个可选的关键字参数

  • reverse, True or False, default=False
  • key, 对比关键字.key=str.lower 来实现忽略大小写的排序,或者是用 key=len 进行基于字符串长度的排序。

用bisect来管理已排序的序列

利用二分查找算法来在有序序列中查找或插入元素

import bisect
bisect.bisect(list, val)

bisect 函数其实是 bisect_right 函数的别名,后者还有个姊妹函数叫bisect_left。它们的区别在于, bisect_left 返回的插入位置是原序列中跟被插入元素相等的元素的位置,也就是新元素会被放置于它相等的元素的前面,而 bisect_right返回的则是跟它相等的元素之后的位置。

bisect.insort(seq, item)把变量 item 插入到序列 seq 中

当列表不是首选时

array

>>> from array import array ➊
>>> from random import random
>>> floats = array('d', (random() for i in range(10**7))) ➋
>>> floats[-1] ➌
0.07802343889111107
>>> fp = open('floats.bin', 'wb')
>>> floats.tofile(fp) ➍
>>> fp.close()
>>> floats2 = array('d') ➎
>>> fp = open('floats.bin', 'rb')
>>> floats2.fromfile(fp, 10**7) ➏
>>> fp.close()
>>> floats2[-1] ➐
0.07802343889111107
>>> floats2 == floats
True
方法 列表 数组  说明
s.__add(s2)__s + s2,拼接
s.__iadd(s2)__s += s2,就地拼接
s.append(e)在尾部添加一个元素
s.byteswap翻转数组内每个元素的字节序列,转换字节序
s.clear()删除所有元素
s.__contains__(e)s 是否含有 e
s.copy()对列表浅复制
s.__copy__()对 copy.copy 的支持
s.count(e)s 中 e 出现的次数
s.__deepcopy__()对 copy.deepcopy 的支持
s.__delitem__(p)删除位置 p 的元素
s.extend(it)将可迭代对象 it 里的元素添加到尾部
s.frombytes(b)将压缩成机器值的字节序列读出来添加到尾部
s.fromfile(f, n)将二进制文件 f 内含有机器值读出来添加到尾部,最多添加 n 项
s.fromlist(l) 将列表里的元素添加到尾部,如果其中任何一个元素导致了 TypeError异常,那么所有的添加都会取消
s.__getitem__(p)s[p],读取位置 p 的元素
s.index(e)找到 e 在序列中第一次出现的位置
s.insert(p, e)在位于 p 的元素之前插入元素 e
s.itemsize数组中每个元素的长度是几个字节
s.__iter__()返回迭代器
s.__len__()len(s),序列的长度
s.__mul__(n)s * n,重复拼接
s.__imul__(n)s *= n,就地重复拼接
s.__rmul__(n)n * s,反向重复拼接*
s.pop([p])删除位于 p 的值并返回这个值, p 的默认值是最后一个元素的位置
s.remove(e)删除序列里第一次出现的 e 元素
s.reverse()就地调转序列中元素的位置
s.__reversed__()返回一个从尾部开始扫描元素的迭代器
s.__setitem__(p,e)s[p] = e,把位于 p 位置的元素替换成 e
s.sort([key],[revers])就地排序序列,可选参数有 key 和 reverse
s.tobytes()把所有元素的机器值用 bytes 对象的形式返回
s.tofile(f)把所有元素以机器值的形式写入一个文件
s.tolist()把数组转换成列表,列表里的元素类型是数字对象
s.typecode返回只有一个字符的字符串,代表数组元素在 C 语言中的类型

内存视图

memoryview 是一个内置类,它能让用户在不复制内容的情况下操作同一个数组的不同切片。 这个功能在处理大型数据集合的时候非常重要。

>>> numbers = array.array('h', [-2, -1, 0, 1, 2])
>>> memv = memoryview(numbers) ➊
>>> len(memv)
5
>>> memv[0] ➋
-2
>>> memv_oct = memv.cast('B') ➌
>>> memv_oct.tolist() ➍
[254, 255, 255, 255, 0, 0, 1, 0, 2, 0]
>>> memv_oct[5] = 4 ➎
>>> numbers
array('h', [-2, -1, 1024, 1, 2]) 

双向队列和其他形式的队列

但是删除列表的第一个元素(抑或是在第一个元素之前添加一个元素)之类的操作是很耗时的,因为这些操作会牵扯到移动列表里的所有元素。
collections.deque 类(双向队列)是一个线程安全、可以快速从两端添加或者删除元素的数据类型。

>>> from collections import deque
>>> dq = deque(range(10), maxlen=10) ➊
>>> dq
deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxlen=10)
>>> dq.rotate(3) ➋
>>> dq
deque([7, 8, 9, 0, 1, 2, 3, 4, 5, 6], maxlen=10)
>>> dq.rotate(-4)
>>> dq
deque([1, 2, 3, 4, 5, 6, 7, 8, 9, 0], maxlen=10)
>>> dq.appendleft(-1) ➌
>>> dq
deque([-1, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxlen=10)
>>> dq.extend([11, 22, 33]) ➍
>>> dq
deque([3, 4, 5, 6, 7, 8, 9, 11, 22, 33], maxlen=10)
>>> dq.extendleft([10, 20, 30, 40]) ➎
>>> dq
deque([40, 30, 20, 10, 3, 4, 5, 6, 7, 8], maxlen=10)
方法 列表 双向队列 说明
s.__add__(s2)s + s2,拼接
s.__iadd__(s2)• s += s2,就地拼接
s.append(e)添加一个元素到最右侧(到最后一个元素之后)
s.appendleft(e)添加一个元素到最左侧(到第一个元素之前)
s.clear()删除所有元素
s.__contains__(e)s 是否含有 e
s.copy()对列表浅复制
s.__copy__()对 copy.copy(浅复制)的支持
s.count(e)s 中 e 出现的次数
s.__delitem__(p)把位置 p 的元素移除
s.extend(i)将可迭代对象 i 中的元素添加到尾部
s.extendleft(i)将可迭代对象 i 中的元素添加到头部
s.__getitem__(p)s[p],读取位置 p 的元素
s.index(e)找到 e 在序列中第一次出现的位置
s.insert(p, e)在位于 p 的元素之前插入元素 e
s.__iter__()返回迭代器
s.__len__()len(s),序列的长度
s.__mul__(n)s * n,重复拼接
s.__imul__(n)s *= n,就地重复拼接
s.__rmul__(n)n * s,反向重复拼接*
s.pop()移除最后一个元素并返回它的值#
s.popleft()移除第一个元素并返回它的值
s.remove(e)移除序列里第一次出现的 e 元素
s.reverse()调转序列中元素的位置
s.__reversed__()返回一个从尾部开始扫描元素的迭代器
s.rotate(n)把 n 个元素从队列的一端移到另一端
s.__setitem__(p, e)s[p] = e,把位于 p 位置的元素替换成 e
s.sort([key], [revers])就地排序序列,可选参数有 key 和 reverse

其他的队列有空在总结.

转载于:https://www.cnblogs.com/yuanoung/p/8440719.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值