# 集合对象

这一节详细介绍了针对 `set` 和 `frozenset` 对象的公共 API。 任何未在下面列出的功能最好是使用抽象对象协议 (包括 `PyObject_CallMethod()`, `PyObject_RichCompareBool()`, `PyObject_Hash()`, `PyObject_Repr()`, `PyObject_IsTrue()`, `PyObject_Print()` 以及 `PyObject_GetIter()`) 或者抽象数字协议 (包括 `PyNumber_And()`, `PyNumber_Subtract()`, `PyNumber_Or()`, `PyNumber_Xor()`, `PyNumber_InPlaceAnd()`, `PyNumber_InPlaceSubtract()`, `PyNumber_InPlaceOr()` 以及 `PyNumber_InPlaceXor()`)。

type PySetObject

  这个 `PyObject` 的子类型被用来保存 `set` 和 `frozenset` 对象的内部数据。 它类似于 `PyDictObject` 的地方在于对小尺寸集合来说它是固定大小的（很像元组的存储方式），而对于中等和大尺寸集合来说它将指向单独的可变大小的内存块（很像列表的存储方式）。 此结构体的字段不应被视为公有并且可能发生改变。 所有访问都应当通过已写入文档的 API 来进行而不可通过直接操纵结构体中的值。

PyTypeObject PySet_Type
  属于 稳定 ABI.

  这是一个 `PyTypeObject` 实例，表示 Python `set` 类型。

PyTypeObject PyFrozenSet_Type
  属于 稳定 ABI.

  这是一个 `PyTypeObject` 实例，表示 Python `frozenset` 类型。

下列类型检查宏适用于指向任意 Python 对象的指针。 类似地，这些构造函数也适用于任意可迭代的 Python 对象。

int PySet_Check(PyObject *p)

  如果 p 是一个 `set` 对象或者是其子类型的实例则返回真值。 此函数总是会成功执行。

int PyFrozenSet_Check(PyObject *p)

  如果 p 是一个 `frozenset` 对象或者是其子类型的实例则返回真值。 此函数总是会成功执行。

int PyAnySet_Check(PyObject *p)

  如果 p 是一个 `set` 对象、`frozenset` 对象或者是其子类型的实例则返回真值。 此函数总是会成功执行。

int PySet_CheckExact(PyObject *p)

  如果 p 是一个 `set` 对象但不是其子类型的实例则返回真值。 此函数总是会成功执行。

  Added in version 3.10.

int PyAnySet_CheckExact(PyObject *p)

  如果 p 是一个 `set` 或 `frozenset` 对象但不是其子类型的实例则返回真值。 此函数总是会成功执行。

int PyFrozenSet_CheckExact(PyObject *p)

  如果 p 是一个 `frozenset` 对象但不是其子类型的实例则返回真值。 此函数总是会成功执行。

PyObject *PySet_New(PyObject *iterable)
  返回值：新的引用。 属于 稳定 ABI.

  返回一个新的 `set`，其中包含 iterable 所返回的对象。 iterable 可以为 `NULL` 表示创建一个新的空集合。 成功时返回新的集合，失败时返回 `NULL`。 如果 iterable 实际上不是可迭代对象则引发 `TypeError`。 该构造器也适用于拷贝集合 (`c=set(s)`)。

PyObject *PyFrozenSet_New(PyObject *iterable)
  返回值：新的引用。 属于 稳定 ABI.

  返回一个新的 `frozenset`，其中包含 iterable 所返回的对象。 iterable 可以为 `NULL` 表示创建一个新的空冻结集合。 成功时返回新的冻结集合，失败时返回 `NULL`。 如果 iterable 实际上不是可迭代对象则引发 `TypeError`。

下列函数和宏适用于 `set` 或 `frozenset` 的实例或是其子类型的实例。

Py_ssize_t PySet_Size(PyObject *anyset)
  属于 稳定 ABI.

  返回 `set` 或 `frozenset` 对象的长度。 等同于 `len(anyset)`。 如果 anyset 不是 `set`, `frozenset` 或其子类型的实例，则会引发 `SystemError`。

Py_ssize_t PySet_GET_SIZE(PyObject *anyset)

  宏版本的 `PySet_Size()`，不带错误检测。

int PySet_Contains(PyObject *anyset, PyObject *key)
  属于 稳定 ABI.

  如果找到则返回 `1` ，如果未找到则返回 `0` ，如果遇到错误则返回 `-1`。 与 Python `__contains__()` 方法不同，该函数不会自动将不可哈希的集合转换为临时冻结集合。 如果 key 是不可哈希对象则会引发 `TypeError`。 如果 anyset 不是 `set`, `frozenset` 或其子类型的实例则会引发 `SystemError`。

int PySet_Add(PyObject *set, PyObject *key)
  属于 稳定 ABI.

  添加 key 到一个 `set` 实例。 也可用于 `frozenset` 实例（与 `PyTuple_SetItem()` 的类似之处是它也可被用来为全新的冻结集合在公开给其他代码之前填充全新的值）。 成功时返回 `0` 而失败时返回 `-1`。 如果 key 为不可哈希对象则会引发 `TypeError`。 如果没有增长空间则会引发 `MemoryError`。 如果 set 不是 `set` 或其子类型的实例则会引发 `SystemError`。

下列函数适用于 `set` 或其子类型的实例，但不可用于 `frozenset` 或其子类型的实例。

int PySet_Discard(PyObject *set, PyObject *key)
  属于 稳定 ABI.

  如果已找到并移除则返回 `1`，如果未找到则返回 `0` (不执行任何操作)，如果遇到错误则返回 `-1`。 不会针对不存在的键引发 `KeyError`。 如果 key 不可哈希则会引发 `TypeError`。 不同于 Python `discard()` 方法，此函数不会自动将不可哈希的集合转换为临时的冻结集合。 如果 set 不是 `set` 或其子类型的实例则会引发 `SystemError`。

PyObject *PySet_Pop(PyObject *set)
  返回值：新的引用。 属于 稳定 ABI.

  返回 set 中任意对象的新引用，并从 set 中移除该对象。 失败时返回 `NULL`。 如果集合为空则会引发 `KeyError`。 如果 set 不是 `set` 或其子类型的实例则会引发 `SystemError`。

int PySet_Clear(PyObject *set)
  属于 稳定 ABI.

  清空现有的所有元素的集合。 成功时返回 `0`。 如果 set 不是 `set` 或其子类型的实际则返回 `-1` 并引发 `SystemError`。

## 已弃用的 API

PySet_MINSIZE

  一个已处于 soft deprecated 状态的表示在 `PySetObject` 实例之内一个内部预分配表的大小的常量。

  该常量只是出于完整性考虑才被写入文档的，因为给定的 CPython 版本并不保证使用具有固定大小的预分配表。 在不涉及不稳定的内部集合的代码中，可以将 `PySet_MINSIZE` 替换为较小的常量如 `8`。

  要查找集合的大小，请改用 `PySet_Size()`。