1.内置序列类型概览
容器序列
list、tuple和collections.deque这些序列能存放不同类型的数据。
扁平序列
str、bytes、bytearray、memoryview和array.array,这类序列只能容纳一种类型。
容器序列存放的是它们所包含的任意类型的对象的引用,而扁平序列里存放的是值而不是
引用。换句话说,扁平序列其实是一段连续的内存空间。由此可见扁平序列其实更加紧
凑,但是它里面只能存放诸如字符、字节和数值这种基础类型。
2.列表推导和生成器表达式
2.1列表推导式
列表推导是构建列表(list)的快捷方式,而生成器表达式则可以用来创建其他任何类型的序列。
示例2-1 把一个字符串变成Unicode码位的列表
>>> symbols = '$¢£¥€¤'
>>> codes = []
>>> for symbol in symbols:
... codes.append(ord(symbol))
...
>>> codes
[36, 162, 163, 165, 8364, 164]
示例2-2 把字符串变成Unicode码位的另外一种写法
>>> symbols = '$¢£¥€¤'
>>> codes = [ord(symbol) for symbol in symbols]
>>> codes
[36, 162, 163, 165, 8364, 164]
列表推导式应用:
使用列表推导计算笛卡儿积
>>> colors = ['black', 'white']
>>> sizes = ['S', 'M', 'L']
>>> tshirts = [(color, size) for color in colors for size in sizes]
>>> tshirts
[('black', 'S'), ('black', 'M'), ('black', 'L'), ('white', 'S'),
('white', 'M'), ('white', 'L')]
2.2 生成器表达式
虽然也可以用列表推导来初始化元组、数组或其他序列类型,但是生成器表达式是更好的选择。这是因为生成器表达式背后遵守了迭代器协议,可以逐个地产出元素,而不是先建立一个完整的列表,然后再把这个列表传递到某个构造函数里。前面那种方式显然能够节省内存。
生成器表达式和列表推导式区别
#生成器表达式( )
#列表推导式[ ]
>>> tb = ((color,size) for color in colors for size in sizes)
>>> tb
<generator object <genexpr> at 0x000000000368A828>
>>> tb.next()
('black', 'S')
>>> tb.next()
('black', 'M')
3.元组不仅仅是不可变的列表
除了用作不可变的列表,它还可以用于没有字段名的记录。
3.1 元组和记录
元组其实是对数据的记录
例如:point = (123,345),该元组表示的是一个点坐标,记录了该点的位置
3.2 元组拆包
元组拆包可以应用到任何可迭代对象上,唯一的硬性要求是,被可迭代对象
中的元素数量必须要跟接受这些元素的元组的空档数一致
例如:
point = (123,234)
x,y = point
x = 123
y = 234
又或是两数据交换
>>> a
1
>>> b
2
>>> a,b = b,a
>>> a
2
>>> b
1
3.3 具名元组
collections.namedtuple是一个工厂函数,它可以用来构建一个带字段名的元组和一个有名字的类。
>>> from collections import namedtuple
>>> city = namedtuple('City','name country population corrdinates')
#其中city是类名,City是元组名字段名
>>> tokyo = city('Tokyo','JP',36.933,(35.689722,139.691667))
>>> tokyo
City(name='Tokyo', country='JP', population=36.933, corrdinates=(35.689722, 139.691667))
作为不可表列表的元组
表2-1:列表或元组的方法和属性(那些由object类支持的方法没有列出来)
方法属性 | 列表 | 元组 | 功能 |
---|---|---|---|
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) |
4 切片
>>> s = 'abcdefd'
>>> s
'abcdefd'
>>> s[2:]
'cdefd'
>>> s[:3]
'abc'
#参数为负数值
>>> s[:-3]
'abcd'
#三个参数
>>> s[1:6:2]
'bdf'
给切片赋值
>>> l = list(range(10))
>>> l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> l[2:5] = [20,30]
>>> l
[0, 1, 20, 30, 5, 6, 7, 8, 9]
#注意
>>> l[2:5] = 100 ➊
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only assign an iterable
>>> l[2:5] = [100]
>>> l
[0, 1, 100, 22, 9]
如果赋值的对象是一个切片,那么赋值语句的右侧必须是个可迭代对象。即便只有单独
一个值,也要把它转换成可迭代的序列。
join函数:
>>>str = "-";
>>>seq = ("a", "b", "c"); # 字符串序列
>>>print str.join( seq );
a-b-c
bisect函数:
bisect是一个排序函数,用来返回所查询元素在元组中的位置(先说明的是,使用这个模块的函数前先确保操作的列表是已排序的。)
bisect.insort(date,123) bisect会根据123的大小与date中数据进行对比,插入到合适大小的位置
列表和数组的属性和方法