第四章 自定义序列类

avatar
作者
筋斗云
阅读量:1

目录

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编程中更好地掌握和应用序列相关的知识。如果您有任何进一步的问题或需要更详细的解释,请随时告诉我!

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!