字典对象

type PyDictObject

PyObject 的子类型表示 Python 字典对象。

PyTypeObject PyDict_Type
属于 稳定 ABI 的一部分。

PyTypeObject 的实例表示 Python 字典类型。这与 Python 层中的 dict 对象相同。

int PyDict_Check(PyObject *p)

如果 p 是一个字典对象或字典类型的子类型的实例,则返回 true。此函数总是成功。

int PyDict_CheckExact(PyObject *p)

如果 p 是一个字典对象,但不是字典类型的子类型的实例,则返回 true。此函数总是成功。

PyObject *PyDict_New()
返回值:新引用。属于 稳定 ABI 的一部分。

返回一个新的空字典,失败时返回 NULL

PyObject *PyDictProxy_New(PyObject *mapping)
返回值:新引用。属于 稳定 ABI 的一部分。

为映射返回一个 types.MappingProxyType 对象,该对象强制执行只读行为。 这通常用于创建视图,以防止修改非动态类类型的字典。

void PyDict_Clear(PyObject *p)
属于 稳定 ABI 的一部分。

清空现有字典的所有键值对。

int PyDict_Contains(PyObject *p, PyObject *key)
属于 稳定 ABI 的一部分。

确定字典 p 是否包含 key。 如果 p 中的某个项目与 key 匹配,则返回 1,否则返回 0。 发生错误时,返回 -1。 这等效于 Python 表达式 key in p

int PyDict_ContainsString(PyObject *p, const char *key)

这与 PyDict_Contains() 相同,但 key 被指定为 const char* UTF-8 编码的字节字符串,而不是 PyObject*

在 3.13 版本中添加。

PyObject *PyDict_Copy(PyObject *p)
返回值:新引用。属于 稳定 ABI 的一部分。

返回一个新字典,其中包含与 p 相同的键值对。

int PyDict_SetItem(PyObject *p, PyObject *key, PyObject *val)
属于 稳定 ABI 的一部分。

使用 key 作为键,将 val 插入到字典 p 中。 key 必须是 可哈希的;如果不是,将引发 TypeError。 成功时返回 0,失败时返回 -1。 此函数不会窃取对 val 的引用。

int PyDict_SetItemString(PyObject *p, const char *key, PyObject *val)
属于 稳定 ABI 的一部分。

这与 PyDict_SetItem() 相同,但 key 被指定为 const char* UTF-8 编码的字节字符串,而不是 PyObject*

int PyDict_DelItem(PyObject *p, PyObject *key)
属于 稳定 ABI 的一部分。

从字典 p 中移除键为 key 的条目。key 必须是 可哈希的;如果不是,则会引发 TypeError 异常。如果 key 不在字典中,则会引发 KeyError 异常。成功时返回 0,失败时返回 -1

int PyDict_DelItemString(PyObject *p, const char *key)
属于 稳定 ABI 的一部分。

此函数与 PyDict_DelItem() 相同,但 key 被指定为 const char* UTF-8 编码的字节字符串,而不是 PyObject*

int PyDict_GetItemRef(PyObject *p, PyObject *key, PyObject **result)
自 3.13 版本起成为 稳定 ABI 的一部分。

返回字典 p 中键为 key 的对象的新的 强引用

  • 如果键存在,则将 *result 设置为值的新的 强引用,并返回 1

  • 如果键不存在,则将 *result 设置为 NULL,并返回 0

  • 发生错误时,引发异常并返回 -1

在 3.13 版本中添加。

另请参阅 PyObject_GetItem() 函数。

PyObject *PyDict_GetItem(PyObject *p, PyObject *key)
返回值:借用的引用。稳定 ABI 的一部分。

返回字典 p 中键为 key 的对象的 借用引用。如果键 key 不存在,则返回 NULL,且设置异常。

注意

在此函数调用 __hash__()__eq__() 方法时发生的异常会被静默忽略。请优先使用 PyDict_GetItemWithError() 函数。

在 3.10 版本中更改: 出于历史原因,允许在没有持有 GIL 的情况下调用此 API。现在不再允许这样做。

PyObject *PyDict_GetItemWithError(PyObject *p, PyObject *key)
返回值:借用的引用。稳定 ABI 的一部分。

PyDict_GetItem() 的变体,它不会抑制异常。如果发生异常,则返回 NULL设置了异常。如果键不存在,则返回 NULL设置异常。

PyObject *PyDict_GetItemString(PyObject *p, const char *key)
返回值:借用的引用。稳定 ABI 的一部分。

此函数与 PyDict_GetItem() 相同,但 key 被指定为 const char* UTF-8 编码的字节字符串,而不是 PyObject*

注意

在此函数调用 __hash__()__eq__() 方法或创建临时 str 对象时发生的异常会被静默忽略。请优先使用 PyDict_GetItemWithError() 函数,并使用您自己的 PyUnicode_FromString() key 来替代。

int PyDict_GetItemStringRef(PyObject *p, const char *key, PyObject **result)
自 3.13 版本起成为 稳定 ABI 的一部分。

PyDict_GetItemRef() 相似,但 key 被指定为 const char* UTF-8 编码的字节字符串,而不是 PyObject*

在 3.13 版本中添加。

PyObject *PyDict_SetDefault(PyObject *p, PyObject *key, PyObject *defaultobj)
返回值:借用引用。

这与 Python 级别的 dict.setdefault() 相同。如果存在,它将返回字典 p 中与 key 对应的值。如果该键不在字典中,则会插入该键,其值为 defaultobj,并返回 defaultobj。此函数仅计算 key 的哈希函数一次,而不是为查找和插入分别独立计算。

在 3.4 版本中添加。

int PyDict_SetDefaultRef(PyObject *p, PyObject *key, PyObject *default_value, PyObject **result)

如果键尚未存在于字典中,则将 default_value 插入到字典 p 中,键为 key。如果 result 不是 NULL,则 *result 将被设置为 default_value强引用(如果键不存在),或者设置为现有值(如果 key 已经存在于字典中)。如果键存在并且未插入 default_value,则返回 1;如果键不存在并且已插入 default_value,则返回 0。如果失败,则返回 -1,设置一个异常,并将 *result 设置为 NULL

为了清楚起见:如果在调用此函数之前你拥有对 default_value 的强引用,则在函数返回后,你将同时拥有对 default_value*result 的强引用(如果它不是 NULL)。它们可能指向同一个对象:在这种情况下,你拥有对它的两个单独的引用。

在 3.13 版本中添加。

int PyDict_Pop(PyObject *p, PyObject *key, PyObject **result)

从字典 p 中删除 key,并可以选择返回已删除的值。如果键不存在,则不引发 KeyError

  • 如果键存在,则在 result 不是 NULL 的情况下,将 *result 设置为对已删除值的新引用,并返回 1

  • 如果键不存在,则在 result 不是 NULL 的情况下,将 *result 设置为 NULL,并返回 0

  • 发生错误时,引发异常并返回 -1

这类似于 dict.pop(),但没有默认值,并且如果键不存在则不引发 KeyError

在 3.13 版本中添加。

int PyDict_PopString(PyObject *p, const char *key, PyObject **result)

类似于 PyDict_Pop(),但 key 被指定为 const char* UTF-8 编码的字节字符串,而不是 PyObject*

在 3.13 版本中添加。

PyObject *PyDict_Items(PyObject *p)
返回值:新引用。属于 稳定 ABI 的一部分。

返回一个 PyListObject,其中包含字典中的所有项。

PyObject *PyDict_Keys(PyObject *p)
返回值:新引用。属于 稳定 ABI 的一部分。

返回一个 PyListObject,其中包含字典中的所有键。

PyObject *PyDict_Values(PyObject *p)
返回值:新引用。属于 稳定 ABI 的一部分。

返回一个 PyListObject,其中包含字典 p 中的所有值。

Py_ssize_t PyDict_Size(PyObject *p)
属于 稳定 ABI 的一部分。

返回字典中的项数。这相当于对字典执行 len(p)

int PyDict_Next(PyObject *p, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue)
属于 稳定 ABI 的一部分。

遍历字典 p 中的所有键值对。在第一次调用此函数开始迭代之前,由 ppos 引用的 Py_ssize_t 必须初始化为 0;该函数为字典中的每个键值对返回 true,并在报告完所有键值对后返回 false。参数 pkeypvalue 应该指向将分别填充每个键和值的 PyObject* 变量,或者可以为 NULL。通过它们返回的任何引用都是借用的。在迭代期间不应更改 ppos。它的值表示内部字典结构中的偏移量,由于该结构是稀疏的,因此偏移量不是连续的。

例如

PyObject *key, *value;
Py_ssize_t pos = 0;

while (PyDict_Next(self->dict, &pos, &key, &value)) {
    /* do something interesting with the values... */
    ...
}

在迭代期间不应修改字典 p。在迭代字典时修改键的值是安全的,但前提是键的集合不发生更改。例如

PyObject *key, *value;
Py_ssize_t pos = 0;

while (PyDict_Next(self->dict, &pos, &key, &value)) {
    long i = PyLong_AsLong(value);
    if (i == -1 && PyErr_Occurred()) {
        return -1;
    }
    PyObject *o = PyLong_FromLong(i + 1);
    if (o == NULL)
        return -1;
    if (PyDict_SetItem(self->dict, key, o) < 0) {
        Py_DECREF(o);
        return -1;
    }
    Py_DECREF(o);
}

在没有外部同步的自由线程构建中,此函数不是线程安全的。您可以使用Py_BEGIN_CRITICAL_SECTION来锁定字典,同时遍历它

Py_BEGIN_CRITICAL_SECTION(self->dict);
while (PyDict_Next(self->dict, &pos, &key, &value)) {
    ...
}
Py_END_CRITICAL_SECTION();
int PyDict_Merge(PyObject *a, PyObject *b, int override)
属于 稳定 ABI 的一部分。

遍历映射对象 b,将键值对添加到字典 a 中。b 可以是字典,或任何支持 PyMapping_Keys()PyObject_GetItem() 的对象。如果 override 为 true,则如果在 b 中找到匹配的键,则会替换 a 中现有的键值对;否则,仅当 a 中没有匹配的键时才会添加键值对。成功时返回 0,如果引发异常则返回 -1

int PyDict_Update(PyObject *a, PyObject *b)
属于 稳定 ABI 的一部分。

这与 C 中的 PyDict_Merge(a, b, 1) 相同,并且类似于 Python 中的 a.update(b),只是 PyDict_Update() 不会回退到迭代键值对序列(如果第二个参数没有“keys”属性)。成功时返回 0,如果引发异常则返回 -1

int PyDict_MergeFromSeq2(PyObject *a, PyObject *seq2, int override)
属于 稳定 ABI 的一部分。

seq2 中的键值对更新或合并到字典 a 中。seq2 必须是生成长度为 2 的可迭代对象的可迭代对象,被视为键值对。如果存在重复的键,则如果 override 为 true,则最后出现的键获胜;否则,第一个出现的键获胜。成功时返回 0,如果引发异常则返回 -1。等效的 Python 代码(返回值除外)

def PyDict_MergeFromSeq2(a, seq2, override):
    for key, value in seq2:
        if override or key not in a:
            a[key] = value
int PyDict_AddWatcher(PyDict_WatchCallback callback)

注册 callback 作为字典观察者。返回一个非负整数 id,该 id 必须传递给未来对 PyDict_Watch() 的调用。如果发生错误(例如,没有更多可用的观察者 ID),则返回 -1 并设置异常。

在 3.12 版本中添加。

int PyDict_ClearWatcher(int watcher_id)

清除由之前从 PyDict_AddWatcher() 返回的 watcher_id 标识的观察者。成功时返回 0,如果发生错误(例如,如果给定的 watcher_id 从未注册)则返回 -1

在 3.12 版本中添加。

int PyDict_Watch(int watcher_id, PyObject *dict)

将字典 dict 标记为受监视。当 dict 被修改或释放时,将调用由 PyDict_AddWatcher() 授予 watcher_id 的回调。成功时返回 0,如果发生错误则返回 -1

在 3.12 版本中添加。

int PyDict_Unwatch(int watcher_id, PyObject *dict)

将字典 dict 标记为不再受监视。当 dict 被修改或释放时,将不再调用由 PyDict_AddWatcher() 授予 watcher_id 的回调。该字典之前必须已由此观察者监视。成功时返回 0,如果发生错误则返回 -1

在 3.12 版本中添加。

type PyDict_WatchEvent

可能的字典观察者事件的枚举:PyDict_EVENT_ADDEDPyDict_EVENT_MODIFIEDPyDict_EVENT_DELETEDPyDict_EVENT_CLONEDPyDict_EVENT_CLEAREDPyDict_EVENT_DEALLOCATED

在 3.12 版本中添加。

typedef int (*PyDict_WatchCallback)(PyDict_WatchEvent event, PyObject *dict, PyObject *key, PyObject *new_value)

字典观察者回调函数的类型。

如果 eventPyDict_EVENT_CLEAREDPyDict_EVENT_DEALLOCATED,则 keynew_value 都将为 NULL。如果 eventPyDict_EVENT_ADDEDPyDict_EVENT_MODIFIED,则 new_value 将是 key 的新值。如果 eventPyDict_EVENT_DELETED,则正在从字典中删除 key,并且 new_value 将为 NULL

dict 之前为空并且另一个字典合并到其中时,会发生 PyDict_EVENT_CLONED。为了保持此操作的效率,在这种情况下不会发出每个键的 PyDict_EVENT_ADDED 事件;而是发出一个 PyDict_EVENT_CLONED,并且 key 将是源字典。

回调可以检查 dict,但不能修改它;这样做可能会产生不可预测的影响,包括无限递归。请勿在回调中触发 Python 代码执行,因为它可能会作为副作用修改字典。

如果 eventPyDict_EVENT_DEALLOCATED,则在回调中对即将销毁的字典获取新的引用会使其复活,并防止其此时被释放。当复活的对象稍后被销毁时,届时处于活动状态的任何观察者回调都将再次被调用。

回调发生在对 dict 的已通知修改发生之前,因此可以检查 dict 的先前状态。

如果回调函数设置了异常,它必须返回 -1;这个异常将使用 PyErr_WriteUnraisable() 作为不可引发的异常打印出来。否则,它应该返回 0

在进入回调函数时,可能已经存在一个待处理的异常。在这种情况下,回调函数应该返回 0,并且仍然设置相同的异常。这意味着回调函数可能无法调用任何其他可能设置异常的 API,除非它首先保存并清除异常状态,并在返回之前恢复它。

在 3.12 版本中添加。