目录
第11条 学会对序列做切片
1、基本写法
凡是实现了__getitem__与__setitem__这两个特殊方法的类都可以切割。
lst = ['a', 'b', 'c', 'd', 'e', 'f']
print(lst[:]) # ['a', 'b', 'c', 'd', 'e', 'f']
print(lst[:5]) # ['a', 'b', 'c', 'd', 'e']
print(lst[-2:]) # ['e', 'f']
# 范围超过列表边界时,会自动忽略不存在的元素
print(lst[:100]) # ['a', 'b', 'c', 'd', 'e', 'f']
2、使用切片赋值
与unpacking形式的赋值不同,使用切片赋值不要求等号两边所指定的元素个数必须相同
lst = ['a', 'b', 'c', 'd', 'e', 'f']
lst[:3] = ['x']
print(lst) # ['x', 'd', 'e', 'f']
注意:
起止位置都留空的切片,如果出现在赋值符号右侧,那么表示给这个列表做副本,这个新列表的内容与原列表相同,但身份不同
lst = ['a', 'b', 'c', 'd', 'e', 'f']
lst0 = lst
lst1 = lst[:]
print(f'lst的地址为{id(lst)}') # lst的地址为2237160819904
print(f'lst0的地址为{id(lst0)}') # lst0的地址为2237160819904
print(f'lst1的地址为{id(lst1)}') # lst1的地址为2237159613440
第12条 不要再切片里同时指定起止下标与步进
步进切片形式:list[start : end : stride]
lst = ['a', 'b', 'c', 'd', 'e', 'f']
a = lst[::3] # ['a', 'd']
b = lst[::-1] # ['f', 'e', 'd', 'c', 'b', 'a']
c = lst[-2:2:-1] # ['e', 'd']
要点:
① 同时指定切片的起止下标与步进值理解起来会很困难
② 如果要指定步进值,那就省略起止下标,而且最好采用整数作为步进值,尽量别用负数。
③ 不要把起点、终点、步进值全都写在同一个切片操作里。如果必须同时使用这三项指标,那就分两次做(其中一次隔位选取,另一次做分割),也可以改用itertools内置模块里的islice方法。
第13条 通过带星号的 unpacking 操作来捕获多个元素,不要用切片
带星号的表达式可以把无法由普通变量接收的那些元素都囊括进去。
lst = [10, 9, 8, 7, 6]
oldest, second_oldest, *other = lst
print(oldest, second_oldest, other) # 10 9 [8, 7, 6]
但是,这种写法至少要有一个普通的接收变量与它搭配,否则会出现SyntaxError。
lst = [10, 9, 8, 7, 6]
*other = lst
print(other)
# SyntaxError: starred assignment target must be in a list or tuple
另外,对于单层结构来说,同一层里最多只能出现一次带星号的unpacking。
lst = [10, 9, 8, 7, 6]
*first, middle, *last = lst
print(first, middle, last)
# SyntaxError: multiple starred expressions in assignment
带星号的表达式总会形成一份列表实例。如果要拆分的序列里已经没有元素了,那么列表就是空白的。
lst = [1, 2]
first, middle, *last = lst
print(first, middle, last) # 1 2 []
第14条 用 sort 方法的 key 参数来表示复杂的排序逻辑
1、列表的sort方法可以根据自然顺序给其中的字符串、整数、元组等内置类型的元素进行排序。默认升序。
a = [(3, 2), (4, 3), (1, 2)]
b = ['ab', 'ba', 'a', 'abc', 'b']
a.sort(), b.sort()
print(a, b)
# [(1, 2), (3, 2), (4, 3)] ['a', 'ab', 'abc', 'b', 'ba']
可以看到,元组在比较大小时,是依次比较每个位置的那两个对应元素,直到能够确定大小为止。字符串比较大小时先根据首字母排序,然后根据字符串长度排序。
2、可以把辅助函数传给sort方法中的key单数,让sort根据这个函数所返回的值来排序。
a = [-2, 1, -4, 3]
a.sort(key=lambda x: abs(x)) # 按绝对值排序
print(a) # [1, -2, 3, -4]
3、如果排序时要依据的指标有很多项,可以把它们放在一个元组中,让key函数返回这样的元组。
class Tool:
def __init__(self, name, weight):
self.name = name
self.weight = weight
def __repr__(self):
return f'Tool({self.name!r}, {self.weight})'
tools = [
Tool('b', 1),
Tool('c', 2),
Tool('d', 1),
Tool('a', 3),
]
# 排序指标:以weight为首要指标排序(从大到小),在weight相同的情况下,在按name排序(从小到大)。
tools.sort(key=lambda x: (-x.weight, x.name))
print(tools)
# [Tool('a', 3), Tool('c', 2), Tool('b', 1), Tool('d', 1)]
4、也可以使用多次调用sort方法,无论多少项排序指标都可以实现
多次调用sort方法,每次调用时分别指定key函数和reverse参数。最次要的指标放在第一轮处理,然后逐步处理更重要的指标,首要指标放在最后一轮处理。
class Tool:
def __init__(self, name, weight):
self.name = name
self.weight = weight
def __repr__(self):
return f'Tool({self.name!r}, {self.weight})'
tools = [
Tool('b', 1),
Tool('c', 2),
Tool('d', 1),
Tool('a', 3),
]
# 排序指标:以weight为首要指标排序(从大到小),在weight相同的情况下,在按name排序(从小到大)。
tools.sort(key=lambda x: x.name)
print(tools)
# [Tool('a', 3), Tool('b', 1), Tool('c', 2), Tool('d', 1)]
tools.sort(key=lambda x: x.weight,
reverse=True)
print(tools)
# [Tool('a', 3), Tool('c', 2), Tool('b', 1), Tool('d', 1)]
5、sort()方法语法
list.sort(cmp=None, key=None, reverse=False)
cmp – 可选参数, 如果指定了该参数会使用该参数的方法进行排序。
key – 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
reverse – 排序规则,reverse = True 降序, reverse = False 升序(默认)。