第2章 列表与字典(一)

第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 升序(默认)。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值