第四章 自定义序列类

目录

5.1 序列类型的分类

容器序列

扁平序列

可变序列

不可变序列

5.2 序列的abc继承关系

5.3 序列的+、+=和extend的区别

+操作符

+=操作符

extend方法

5.4 实现可切片的对象

5.5 bisect管理可排序序列

深入解释

5.6 什么时候我们不该用列表

深入解释

5.7 列表推导式、生成器表达式、字典推导式

列表推导式

生成器表达式

字典推导式

5.8 本章小结


在Python编程中,序列类型是最常用的数据结构之一。理解和掌握各种序列类型及其操作对于编写高效、可读性强的代码至关重要。本章将深入探讨Python中序列类型的分类、使用及实现自定义序列类的方法。

5.1 序列类型的分类

Python中的序列类型主要分为以下几类:

  1. 容器序列(list、tuple、collections.deque)
  2. 扁平序列(str、bytes、bytearray、array.array)
  3. 可变序列(list、deque、bytearray、array)
  4. 不可变序列(str、tuple、bytes)
容器序列

容器序列包含对不同类型对象的引用,可以存储任意类型的对象。常见的容器序列包括listtuplecollections.deque

示例代码:

from collections import deque

list_container = [1, 'a', 3.14]
tuple_container = (1, 'a', 3.14)
deque_container = deque([1, 'a', 3.14])

print(list_container)
print(tuple_container)
print(deque_container)
扁平序列

扁平序列存储值本身,而不是对对象的引用。常见的扁平序列包括strbytesbytearrayarray.array

示例代码:

import array

str_flat = 'hello'
bytes_flat = b'hello'
bytearray_flat = bytearray(b'hello')
array_flat = array.array('i', [1, 2, 3, 4])

print(str_flat)
print(bytes_flat)
print(bytearray_flat)
print(array_flat)
可变序列

可变序列是可以在原地修改的序列类型,包括listdequebytearrayarray

示例代码:

list_mutable = [1, 2, 3]
list_mutable[0] = 4

deque_mutable = deque([1, 2, 3])
deque_mutable.append(4)

bytearray_mutable = bytearray(b'hello')
bytearray_mutable[0] = ord('H')

print(list_mutable)
print(deque_mutable)
print(bytearray_mutable)
不可变序列

不可变序列不能在原地修改,一旦创建就不能改变。常见的不可变序列包括strtuplebytes

示例代码:

str_immutable = 'hello'
tuple_immutable = (1, 2, 3)
bytes_immutable = b'hello'

print(str_immutable)
print(tuple_immutable)
print(bytes_immutable)

5.2 序列的abc继承关系

Python的collections.abc模块提供了许多抽象基类,这些基类定义了序列的基本接口,允许我们自定义符合这些接口的序列类型。

通过继承collections.abc模块中的抽象基类,可以确保自定义的序列类型实现了必要的方法和行为。例如,可以继承collections.abc.Sequence来创建一个自定义的不可变序列。

高级示例代码:

from collections.abc import Sequence

class MySequence(Sequence):
    def __init__(self, data):
        self._data = data
    
    def __getitem__(self, index):
        return self._data[index]
    
    def __len__(self):
        return len(self._data)
    
my_seq = MySequence([1, 2, 3])
print(len(my_seq))  # 输出 3
print(my_seq[1])    # 输出 2

5.3 序列的++=extend的区别

在Python中,序列操作符++=和方法extend虽然都可以用来合并序列,但它们在实现和性能上有所不同。

+操作符

+操作符用于生成一个新的序列对象,将两个序列合并。适用于不可变序列和可变序列。

示例代码:

list1 = [1, 2, 3]
list2 = [4, 5, 6]
list3 = list1 + list2  # 新建了一个列表

print(list3)  # 输出 [1, 2, 3, 4, 5, 6]
+=操作符

+=操作符用于就地修改可变序列,效率较高。对于不可变序列,+=等同于+操作符。

示例代码:

list1 = [1, 2, 3]
list1 += [4, 5, 6]  # 就地修改

print(list1)  # 输出 [1, 2, 3, 4, 5, 6]
extend方法

extend方法是特有的可变序列方法,效率最高,可以就地修改序列。

示例代码:

list2 = [1, 2, 3]
list2.extend([4, 5, 6])  # 就地修改

print(list2)  # 输出 [1, 2, 3, 4, 5, 6]

5.4 实现可切片的对象

要实现支持切片操作的自定义序列类,需要实现__getitem__方法,并处理切片对象。Python的切片操作通过slice对象实现。自定义序列类需要检查传递给__getitem__的参数是否为slice对象,并相应地处理切片逻辑。

高级示例代码:

class MySequence(Sequence):
    def __init__(self, data):
        self._data = data
    
    def __getitem__(self, index):
        if isinstance(index, slice):
            return self._data[index.start:index.stop:index.step]
        return self._data[index]
    
    def __len__(self):
        return len(self._data)
    
my_seq = MySequence([1, 2, 3, 4, 5])
print(my_seq[1:4])  # 输出 [2, 3, 4]

5.5 bisect管理可排序序列

bisect模块用于管理有序序列,可以高效地插入和查找元素。常用函数包括bisect_leftbisect_rightinsort

深入解释

bisect模块提供了二分查找算法,适用于有序序列。insort函数可以在保持序列有序的情况下插入新元素。

高级示例代码:

import bisect

sorted_list = [1, 3, 4, 7]
bisect.insort(sorted_list, 5)  # 在保持有序的情况下插入

print(sorted_list)  # 输出 [1, 3, 4, 5, 7]

index = bisect.bisect_left(sorted_list, 5)
print(index)  # 输出 3

5.6 什么时候我们不该用列表

列表虽然灵活且易用,但在某些情况下并不是最佳选择。例如,需要频繁插入或删除元素时,collections.deque可能是更好的选择。

深入解释

列表的随机访问速度快,但在头部插入或删除元素时效率较低。对于这些场景,可以考虑使用deque或者其他适合的数据结构。

高级示例代码:

from collections import deque

# 使用 deque 进行高效的头部操作
dq = deque([1, 2, 3])
dq.appendleft(0)  # 在头部插入

print(dq)  # 输出 deque([0, 1, 2, 3])

dq.popleft()  # 从头部删除

print(dq)  # 输出 deque([1, 2, 3])

5.7 列表推导式、生成器表达式、字典推导式

Python提供了列表推导式、生成器表达式和字典推导式,使得创建和处理序列更加简洁和高效。

列表推导式

列表推导式是创建列表的简洁方式,语法为[expression for item in iterable if condition]

示例代码:

squares = [x ** 2 for x in range(10)]
print(squares)  # 输出 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
生成器表达式

生成器表达式类似于列表推导式,但返回的是一个生成器对象,节省内存。

示例代码:

squares_gen = (x ** 2 for x in range(10))
for square in squares_gen:
    print(square)  # 逐个输出 0, 1, 4, 9, ...
字典推导式

字典推导式用于创建字典,语法为{key: value for item in iterable if condition}

示例代码:

squares_dict = {x: x ** 2 for x in range(10)}
print(squares_dict)  # 输出 {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}

5.8 本章小结

在本章中,我们详细探讨了Python中序列类型的分类和实现,包括容器序列、扁平序列、可变序列和不可变序列。通过具体示例,我们展示了如何使用collections.abc模块创建自定义序列类,如何高效地管理排序序列,及何时避免使用列表。此外,我们还讨论了列表推导式、生成器表达式和字典推导式的用法。

通过这些内容,读者可以更深入地理解Python中的序列操作和实现,进而编写出更高效、可维护的代码。希望这篇博客能够帮助您在Python编程中更好地掌握和应用序列相关的知识。如果您有任何进一步的问题或需要更详细的解释,请随时告诉我!

  • 12
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

深度学习客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值