Effective Python (Second Edition) 笔记——列表与字典

目录

11、学会对序列做切片

12、不要在切片里同时指定起止下标与步进

13、通过带星号的 unpacking 操作来捕获多个元素,不要用切片

14、用 sort 方法的 key 参数来表示复杂的逻辑排序


11、学会对序列切片

  • 凡是实现了 __getitem__ 与 __setitem__ 这两个特殊方法的类都可以切割。
  • 开始省略下标0,结束省略结尾下标,负数下标表示倒数。
  • 如果起点、终点越界,会自动忽略不存在的元素,很容易构造出最多只有若干元素的序列。
  • 切割出来的列表是一份全新的列表,即便把某个元素换掉,也不会影响原列表中相应位置。
  • 切片可以出现在赋值符号左侧,表示用右侧那些元素把原列表中这个范围内元素换掉。不要求等号两边所指定的元素个数必须相同。原列表中,位于切片范围之前和之后的那些元素会予以保留,但是列表的长度可能有所变化。
  • 起点、终点位置都留空的切片,出现在赋值符号右侧,表示给列表做副本。内容相同,身份却不同。
  • 把不带起点、终点的切片放在赋值符号左边,表示用右边列表的副本把左侧列表全部内容替换掉。
a = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
b = a[3:]
print('Before:    ', b)
b[1] = 99
print('After:     ', b)
print('No change: ', a)

------------------------------------------------
>>> Before:    ['d', 'e', 'f', 'g', 'h']
    After:     ['d', 99, 'f', 'g', 'h']
    No change: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
print('Before:    ', a)
a[2:7] = [99, 22, 14]
print('After:     ', a)
a[2:3] = [47, 11]
print('After:     ', a)

-------------------------
>>> Before:    ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
    After:     ['a', 'b', 99, 22, 14, 'h']
    After:     ['a', 'b', 47, 11, 22, 14, 'h']
b = a
print('Before a', a)
print('Before b', b)
a[:] = [101, 102, 103]
print('After a', a)
print('After b', b)

-------------------------
>>> Before a ['a', 'b', 47, 11, 22, 14, 'h']
    Before b ['a', 'b', 47, 11, 22, 14, 'h']
    After a [101, 102, 103]
    After b [101, 102, 103]

12、不要切片同时指定起止下标步进

  • 列表、bytes 类型的字符串、Unicode 形式的字符串可以用步进 -1 来反转;UTF-8 字符串不能用这个技巧反转。
  • 同时使用起止下标与步进会让切片很难懂。如果必须指定步进,尽量采用正数,而且要把起止下标都留空。
  • 即便必须同时使用步进值与起止下标,也应该考虑分成两次来写。
  • 先隔位选取,然后再切割,会让程序多做一次浅拷贝,所以应该把最能缩减列表长度的那个切片操作放在前面。
y = x[::2]
z = y[1:-1]

13、通过带星号的 unpacking 操作来捕获多个元素,不要切片

  • 这种写法至少要有一个普通的接受变量与它搭配,否则就会出现语法错误。不能只使用带星号的表达式而不搭配普通变量。
  • 对于单层结构来说,同一级里面最多只能出现一次带星号的 unpacking。
  • 带星号的表达式会形成一份0个或多个值的列表实例(有可能耗尽计算机的全部内存并导致程序崩溃,首先必须确定系统有足够的内存可以存储拆分出来的结果数据),如果拆分的序列里已经没有元素留给它了,列表就是空白的。
car_ages_descending = [20, 19, 15, 9, 8, 7, 6, 4, 1, 0]
oldest, second_oldest, *others = car_ages_descending
print(oldest, second_oldest, others)

------------------------------------------------------------
>>> 20 19 [15, 9, 8, 7, 6, 4, 1, 0]
car_ages_descending = [20, 19, 15, 9, 8, 7, 6, 4, 1, 0]
oldest, *others, youngest = car_ages_descending
print(oldest, youngest, others)

------------------------------------------------------------
>>> 20 0 [19, 15, 9, 8, 7, 6, 4, 1]
car_ages_descending = [20, 19, 15, 9, 8, 7, 6, 4, 1, 0]
*others, second_youngest, youngest = car_ages_descending
print(youngest, second_youngest, others)

------------------------------------------------------------
>>> 0 1 [20, 19, 15, 9, 8, 7, 6, 4]

14、用 sort 方法的 key 参数来表示复杂的逻辑排序

  • list 类型的 sort 方法总是按照自然升序排列列表内的元素。
  • 可以把排序逻辑定义成函数,然后将这个函数传递给 sort 方法的 key 参数。(key 函数本身应该带有一个参数,指代列表中有待排序的对象,函数返回的应该是个可比较的值)
  • 排序时依据的指标有很多项,可以放在一个元组中,元组之间是可以比较的,依次比较每个位置的两个对应元素,直到能够确定大小为止。
  • 如果在某一指标上采用“-”可以实现按逆序排序。
  • sort 方法的一项特征:稳定的排序算法,如果 key 函数认定两个值相等,这两个值在排序结果中的先后顺序会与它们在排序前的顺序一致。可以在同一个列表上多次调用 sort 方法,每次指定不同的排序指标,指定 key 函数和 reverse 参数。把首要指标放在第二轮,次要指标放在第一轮。无论有多少项排序指标都可以按照这种思路来实现,而且每项指标可以分别按照各自的方向来排,不用全部是升序或降序。最重要的排序指标放在最后一轮处理。(只有迫不得已的时候,才考虑多次调用 sort 方法)
tools.sort(key=lambda x: x.name)
tools.sort(key=lambda x: x.weight)
# 以下两种方式会让 weight 和 name 均按同样方向排序
tools.sort(key=lambda x: (x.weight, x.name))
tools.sort(key=lambda x: (x.weight, x.name), reverse=True))
# 利用-进行逆序排序,但是name这种str不支持-运算符
tools.sort(key=lambda x: (-x.weight, x.name))

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值