Python 序列类型

序列(Sequence)是有顺序的数据列,Python 有三种基本序列类型:list, tuple 和 range 对象,序列(Sequence)是有顺序的数据列,二进制数据(bytes) 和 文本字符串(str)也是序列类型,它们是特殊序列类型,会有一些特殊的性质和操作。

序列类型

Python 的内置序列类型有:

类型创建方法可变性特别方法
列表list()可变sort()
元组tuple()不可变
等差数列range()不可变属性方法
字符串str()不可变字符的方法
字节串bytes()不可变
字节数组bytearray()可变
内存视图memoryview()不可变

要注意的是,集合、字典不是序列类型,虽然字典在最新的 Python 版本中具备了元素顺序特性,但这不是一种「保证」。

如何判断一个数据是不是序列类型呢?

from collections import abc

a = [1, 2, 3]
b = {1, 2, 3}
c = (1, 2, 3)

isinstance(a, abc.Sequence)
# True
isinstance(b, abc.Sequence)
# False

# 可变类型
isinstance(a, abc.MutableSequence)
# True
isinstance(c, abc.MutableSequence)
# False

序列操作

序列的特点是由若干元素组成,元素的分布有顺序,因此根据这个特点,它们支持一些共性的操作。

通用操作

以下是所有序列类型均支持的操作:

运算结果:备注
x in s如果 s 中的某项等于 x 则结果为 True,否则为 False
x not in s如果 s 中的某项等于 x 则结果为 False,否则为 True
s + ts 与 t 相拼接
s * n 或 n * s相当于 s 与自身进行 n 次拼接
s[i]s 的第 i 项,起始为 0切片操作
s[i:j]s 从 i 到 j 的切片
s[i:j:k]s 从 i 到 j 步长为 k 的切片
len(s)s 的长度
min(s)s 的最小项
max(s)s 的最大项
s.index(x[, i[, j]])x 在 s 中首次出现项的索引号
(索引号在 i 或其后且在 j 之前)
count 方法
s.count(x)x 在 s 中出现的总次数index 方法
for i in x:pass迭代
hash(x)对象的哈希值仅不可变序列
sorted(x)排序
all(x) 或者 any(x)全真或者有真检测
iter(x)生成迭代器

注:以上部分操作需要额外的特殊方法实现。当我们在处理数据量大且需频繁查找元素(如 in 操作)时,最好使用 set、dict ,这样将会大幅度提升处理速度。

可变序列类型

以下是仅可变序列支持的操作:

运算结果:备注
s[i] = x将 s 的第 i 项替换为 x
s[i:j] = t将 s 从 i 到 j 的切片替换为可迭代对象 t 的内容
del s[i:j]等同于 s[i:j] = []
s[i:j:k] = t将 s[i:j:k] 的元素替换为 t 的元素
del s[i:j:k]从列表中移除 s[i:j:k] 的元素
s.append(x)将 x 添加到序列的末尾
(等同于 s[len(s):len(s)] = [x])
s.clear()从 s 中移除所有项 (等同于 del s[:])
s.copy()创建 s 的浅拷贝 (等同于 s[:])
s.extend(t) 或 s += t用 t 的内容扩展 s
(基本上等同于 s[len(s):len(s)] = t)
s *= n使用 s 的内容重复 n 次来对其进行更新
s.insert(i, x)在由 i 给出的索引位置将 x 插入 s
(等同于 s[i:i] = [x])
s.pop() 或 s.pop(i)提取在 i 位置上的项,并将其从 s 中移除
s.remove(x)删除 s 中第一个 s[i] 等于 x 的项目。
s.reverse()就地将列表中的元素逆序。

序列的本质

序列是一种可迭代(iterable)的对象,它支持通过 __getitem__() 特殊方法来使用整数索引进行高效的元素访问,并定义了一个返回序列长度的 __len__() 方法。内置的序列类型有 list、str、tuple 和 bytes。注意虽然 dict 也支持 __getitem__() 和 __len__(),但它被认为属于映射而非序列,因为它查找时使用任意的不可变的(immutable)键而非整数。

collections.abc.Sequence 抽象基类定义了一个更丰富的接口,它在 __getitem__() 和 __len__() 之外又添加了 count()、index()、__contains__() 和 __reversed__()。 实现此扩展接口的类型可以使用 register() 来显式地注册。

实现示例

我们定义一个包的类,包有名字和存放的一系列物品。根据序列原理,我们将其实现为一个序列,支持序列的一些操作来读取包里物品。

class Bag():
    def __init__(self, name, contents) -> None:
        self.name = name
        self.contents = contents

    def __repr__(self) -> str:
        return f'<Bag: {self.name}>'

    def __len__(self):
        return len(self.contents)

    def __getitem__(self, idx):
        return self.contents[idx]

我们来实例化并进行操作,实例化一个钱包,里边存放不同面额的人民币:

# 实例化为一个钱包
w = Bag('wallet', [1, 5, 10, 20, 100])
w
# <Bag: wallet>

进行一些序列的操作:

max(w) # 100
len(w) # 5
w[-1] # 100
10 in w # True
for i in w: print(i)
'''
1
5
10
20
100
'''
hash(w) # 8766419859204
all(w) # True
sorted(w) # [1, 5, 10, 20, 100]
[*reversed(w)] # [100, 20, 10, 5, 1]
iter(w) # <iterator at 0x7f91757771f0>
  • 19
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

高亚奇

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

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

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

打赏作者

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

抵扣说明:

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

余额充值