Skip to content

字典和集合

几种数据类型在内存中的访问方式

  • 直接访问:数字
  • 顺序访问:字符串 列表 元组
  • 映射访问:字典

字典

dict

可下标类型(subscriptable) 可迭代类型(Iterable) 可变类型(mutable) 无序类型 一系列键值对 key-value 用冒号分割,格式如下:

python
d = {"key1": "value1", "key2": "value2"}

key 必须是不可变类型的数据(否则报错 unhashable)
value 可以是任意数据类型
如果 key 使用布尔值会被转换为 1 和 0

解构赋值

python
d2 = {"key0": None, **d}

在 python3.6 以上版本中,字典默认按插入的顺序排列了键值对。
在 python3.8 以上版本中,字典可以使用 reversed()按插入顺序反向迭代

索引

in 成员运算符

python
"key1" in d  # 判断键是否存在 返回布尔值

getitem 操作

shell
>>> d['key1']
'value1'

setitem 操作

shell
d["key1"] = "debu"

有关的内置函数

len(dict)返回键的数目

zip()以拉链法惰性生成键值对:('a','b','c'),(1,2,3) ->[('a',1),('b',2)('c',3)]

dict() 以键值对生成字典:[('a',1),('b',2),('c',3)] -> {'a':1,'b':2,'c':3};也可将有 keys 方法的可下标对象强制转换

常用方法

dict.fromkeys(可迭代对象,value)静态方法生成字典,所有键的值都为 value

.copy() 浅拷贝

增删改查

.setdefault(key, value)已存在则返回已存在的 value,不存在则设置。

.update(key=value) .update(dict)设置或覆盖,这里可对比之后章节函数的剩余参数。

.pop(key, None)删除并返回其 value,不存在则返回第二个参数,第二个参数默认为 None。

.popitem()随机删一个并返回其键值对。

.clear()清空。

del d[key1] 删除一组键值对。

.get(key, None)查找 不存在则返回第二个参数 默认为 None。

.items()返回键值对组成的列表。功能与dict()相反。

.keys()返回键组成的列表,可下标对象转化为字典需要有这个方法。

.values()返回值组成的列表。

字典合并

python3.9+

合并 (|) 与更新 (|=) 运算符。为现有的 {**d1, **d2}dict.update字典合并方法提供了补充。

python
x = {"key1": "value1 from x", "key2": "value2 from x"}
y = {"key2": "value2 from y", "key3": "value3 from y"}
x | y
# {'key1': 'value1 from x', 'key2': 'value2 from y', 'key3': 'value3 from y'}
y | x
# {'key2': 'value2 from x', 'key3': 'value3 from y', 'key1': 'value1 from x'}

集合

set

可迭代类型(Iterable) 可变类型(mutable) 无序类型,元素不重复

生成方式:

  1. {1,2,3,4,5}
  2. set(可迭代对象)

规范的初始化

创建一个空字典或空集合的时候使用dict()set()
而不是使用{}

增删方法

python
s1.add(p_obj)
s1.update(s2)
s.claer()  # 清空
s.pop()  # 随机删除一个并返回其值
s.remove(value)  # 删除 没有=>报错
s.discard(value)  # 删除 没有不报错

浅拷贝

python
s.copy()  # 如果是list直接使用切片就可以浅拷贝arr2=arr[:]

集合之间运算

运算运算符表示对象方法
交集s1&s2s1.intersection(s2)
并集s1|s2s1.union(s2)
差集s1-s2s1.difference(s2)
交叉补集s1.symmetric_difference(s2)
python
s1.issubset(s2)  # s1是否是s2子集
s1.issuperset(s2)  # s1是否是s2超集
s1.intersection_update(s2)
s1.difference_update(s2)
s1.symmetric_difference_update(s2)

内置函数 set()frozenset()分别用来生成可变和不可变的集合

枚举类

enum 模块的枚举类包括

  • Enum 枚举类
  • IntEnum 值只能是 int 的枚举子类
  • Flag 可参与和 Flag 的位运算且保持成员的枚举子类
  • IntFlag 可参与和 int 的位运算且保持成员的枚举子类

创建

python
from enum import Enum


class Color(Enum):
    RED = (255, 0, 0)
    GREEN = (0, 255, 0)
    BLUE = (0, 0, 255)

枚举成员可以按值查找,属性访问或下标访问,可以 hash

shell
>>> Color((0,0,255)) # 按值查找
<Color.BLUE: (0, 0, 255)>
>>> Color.RED # 属性访问
<Color.RED: (255, 0, 0)>
>>> Color['RED'] # 下标访问
<Color.RED: (255, 0, 0)>

拥有相同的值,后定义的成员是先定义的成员的别名,优先返回先定义的成员

@unique

枚举专用的类装饰器@enum.unique。它不允许别名存在

python
from enum import Enum, unique


@unique
class Color(Enum):
    AQUA = (0, 255, 255)
    CYAN = (0, 255, 255)


# raise ValueError
# ValueError: duplicate values found in <enum 'Color'>: CYAN -> AQUA

__members__

映射了成员的有序字典

shell
>>> for i in Color.__members__.items():
...     print(i)

('RED', <Color.RED: (255, 0, 0)>)
('GREEN', <Color.GREEN: (0, 255, 0)>)
('BLUE', <Color.BLUE: (0, 0, 255)>)

拥有成员的枚举类不允许被继承。枚举类也不能实例化。

但是很自然地,枚举成员应该被当作实例来看待,无论是类型注解还是魔术方法。

格式化输出

使用.name.value来输出

shell
>>> Color.RED.name
'RED'
>>> Color.BLUE.value
(0, 0, 255)

配合魔术方法__repr__和内置函数repr来输出,成员就像实例一样。

python
class HTTP_method(Enum):
    get = "GET"
    post = "POST"
    put = "PUT"
    delete = "DELETE"
    patch = "PATCH"

    def __repr__(self):
        return repr(self.value)


HTTP_method.get
# 'GET'