1. 内置序列类型概览
-
容器序列
能存放不同类型数据,因为存放的是任意对象的引用 -
扁平序列
只能存放相同类型的数据,因为存放的是值
除了list、tuple和collections.deque,其他常见的序列都是扁平序列
除了tuple、str、bytes,其他常见序列都是可变序列(可以被修改)
2. 列表推导
列表推导、生成器表达式,以及同它们很相似的集合(set)推导和字典(dict)推导,在 Python 3 中都有自己的局部作用域,因此表达式内部的变量和赋值只在局部起作用
>>> x='ABC'
>>> dummy=[ord(x) for x in x]
>>> x
'ABC'
>>> dummy
[65,66,67]
3. 生成器表达式
生成器表达式的语法跟列表推导差不多,只不过把方括号换成圆括号而已。
生成器表达式相比列表推导是更好的选择,因为生成器表达式背后遵守了迭代器协议,可以逐个地产出元素,而不是先建立一个完整的列表,能够节省内存
colors=['black','white']
sizes=['S','M','L']
g=('%s %s' % (c,s) for c in colors for s in sizes)
for t in g:
print(t)
4. 元组
元组不仅仅是不可变的列表,元组其实是对数据的记录:元组中的每个元素位置固定,正是这个位置信息给数据赋予了意义。如:
# 表示经纬度
lax_coordinates = (33.9425, -118.408056)
值得注意的是,除了跟增减元素相关的方法之外,元组支持列表的其他所有方法
4.1.元组拆包
- 最好辨认的元组拆包形式就是平行赋值,也就是说把一个可迭代对象里的元素,就像下面这段代码:
接受表达式的元组可以是嵌套的,例如:(a, b, (c, d))>>> lax_coordinates = (33.9425, -118.408056) >>> latitude, longitude = lax_coordinates # 元组拆包 >>> latitude 33.9425 >>> longitude -118.408056
- 在元组拆包中使用 * 也可以帮助我们把注意力集中在元组的部分元素上
>>> a, b, *rest = range(5) >>> a, b, rest (0, 1, [2, 3, 4]) >>> a, b, *rest = range(3) >>> a, b, rest (0, 1, [2]) >>> a, b, *rest = range(2) >>> a, b, rest (0, 1, [])
4.2.namedtuple
用 namedtuple
构建的类的实例所消耗的内存跟元组是一样的,因为字段名都被存在对应的类里面。这个实例跟普通的对象实例比起来也要小一些,因为 Python 不会用 __dict__
来存放这些实例的属性。
>>> from collections import namedtuple
>>> City = namedtuple('CITY', 'name country population coordinates') # 注意类名和实例名
>>> tokyo = City('Tokyo', 'JP', 36.933, (35.689722, 139.691667))
>>> tokyo
CITY(name='Tokyo', country='JP', population=36.933, coordinates=(35.689722, 139.691667))
创建一个具名元组需要两个参数,一个是类名,另一个是类的各个字段的名字。后者可以是由数个字符串组成的可迭代对象,或者是由空格分隔开的字段名组成的字符串。
5. 切片
为什么切片和区间会忽略最后一个元素:
- 快速看出切片和区间里有几个元素
- (下标相减)快速计算出切片和区间的长度
- 可以利用任意一个下标来把序列分割成不重叠的两部分
切片的操作如下:
>>> 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]
>>> del l[5:7]
>>> l
[0, 1, 20, 30, 5, 8, 9]
>>> l[3::2] = [11, 22]
>>> l
[0, 1, 20, 11, 5, 22, 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]
6.增量赋值
对不可变序列进行重复拼接操作的话,效率会很低,因为每次都有一个新对象,而解释器需要把原来对象中的元素先复制到新的对象里,然后再追加新的元素。但是str是一个例外,因为+=操作太普遍,因此CPython对它进行了优化。
注意不要把可变对象放在元组里,因为增量赋值不是一个原子操作:
>>> t = (1, 2, [30, 40])
>>> t[2] += [50, 60]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> t
(1, 2, [30, 40, 50, 60])
7.list.sort和sorted
区别仅在于,list.sort
就地排序,返回None,而sorted
新建一个list,返回排序后的list
- 参数 reverse:设为True会降序排序,默认为False
- 参数 key:key传入某个函数,该函数会被用在序列里的每一个元素上,所产生的结果将是排序算法依赖的对比关键字。在字符串排序中,常见的有
key=str.lower
(不区分大小写排序)或key=len
(字符串长度排序),这个参数默认值是恒等函数
8.bisect
可以先用 bisect(haystack, needle)
查找位置index,再用 haystack.insert(index, needle)
来插入新值。但也可用 insort
来一步到位,并且后者的速度更快一些。
>>> import bisect
>>> a=[1,2,3]
>>> bisect.bisect(a,1)
1
>>> a.insert(1,1)
>>> a
[1, 1, 2, 3]
>>> bisect.insort(a,2.5)
>>> a
[1, 1, 2, 2.5, 3]
bisect
函数其实是 bisect_right
函数的别名,后者还有个姊妹函数叫 bisect_left
。bisect_left
返回的插入位置是原序列中跟被插入元素相等的元素的位置,也就是新元素会被放置于它相等的元素的前面,而 bisect_right 返回的则是跟它相等的元素之后的位置。
用例(分数评级):
'''
(-∞,60) F
[60,70) D
[70.80) C
[80,90) B
[90,+∞) A
'''
>>> def grade(score, breakpoints=[60, 70, 80, 90], grades='FDCBA'):
... i = bisect.bisect(breakpoints, score)
... return grades[i]
...
>>> [grade(score) for score in [33, 99, 77, 70, 89, 90, 100]]
['F', 'A', 'C', 'C', 'B', 'A', 'A']
标签:流畅,bisect,元素,list,rest,元组,Python0202,数组,序列
From: https://www.cnblogs.com/southtonorth/p/17196273.html