Following system colour scheme - Python 增强提案 Selected dark colour scheme - Python 增强提案 Selected light colour scheme - Python 增强提案

Python 增强提案

PEP 351 – 冻结协议

作者:
Barry Warsaw <barry at python.org>
状态:
已拒绝
类型:
标准跟踪
创建日期:
2005年4月14日
Python 版本:
2.5
发布历史:


目录

摘要

本PEP描述了一个简单的协议,用于请求可变对象的冻结、不可变副本。它还定义了一个新的内置函数,该函数使用此协议为任何协作对象提供不可变副本。

拒绝通知

此PEP被拒绝。原因请参见python-dev上的此讨论串

基本原理

字典和集合等内置对象只接受不可变对象作为键。这意味着列表等可变对象不能用作字典的键。然而,Python程序员可以将列表转换为元组;这两个对象相似,但后者是不可变的,可以用作字典键。

可以想象,第三方对象也有类似的可变和不可变对应物,并且拥有一个用于此类对象转换的标准协议将非常有用。

sets.Set对象公开了一个“自动转换为不可变的协议”,以便您可以创建sets.Setsets.SetPEP 218故意从内置集合中删除了此功能。本PEP提出此功能仍然有用,并提出了一个支持它的标准机制。

提案

建议添加一个名为freeze()的新内置函数。

如果freeze()传入一个不可变对象(通过在该对象上调用hash()没有引发TypeError来确定),则直接返回该对象。

如果freeze()传入一个可变对象(即该对象的hash()引发TypeError),则freeze()将调用该对象的__freeze__()方法以获取不可变副本。如果对象没有__freeze__()方法,则会引发TypeError

示例实现

以下是freeze()内置函数的Python实现

def freeze(obj):
    try:
        hash(obj)
        return obj
    except TypeError:
        freezer = getattr(obj, '__freeze__', None)
        if freezer:
            return freezer()
        raise TypeError('object is not freezable')

以下是一些显示预期语义的代码示例

class xset(set):
    def __freeze__(self):
        return frozenset(self)

class xlist(list):
    def __freeze__(self):
        return tuple(self)

class imdict(dict):
    def __hash__(self):
        return id(self)

    def _immutable(self, *args, **kws):
        raise TypeError('object is immutable')

    __setitem__ = _immutable
    __delitem__ = _immutable
    clear       = _immutable
    update      = _immutable
    setdefault  = _immutable
    pop         = _immutable
    popitem     = _immutable

class xdict(dict):
    def __freeze__(self):
        return imdict(self)
>>> s = set([1, 2, 3])
>>> {s: 4}
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: set objects are unhashable
>>> t = freeze(s)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "/usr/tmp/python-lWCjBK.py", line 9, in freeze
TypeError: object is not freezable
>>> t = xset(s)
>>> u = freeze(t)
>>> {u: 4}
{frozenset([1, 2, 3]): 4}
>>> x = 'hello'
>>> freeze(x) is x
True
>>> d = xdict(a=7, b=8, c=9)
>>> hash(d)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: dict objects are unhashable
>>> hash(freeze(d))
-1210776116
>>> {d: 4}
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: dict objects are unhashable
>>> {freeze(d): 4}
{{'a': 7, 'c': 9, 'b': 8}: 4}

参考实现

补丁1335812提供了此功能的C语言实现。它添加了freeze()内置函数,以及列表和集合的__freeze__()方法的实现。字典在当前的Python中不容易冻结,因此尚未提供dict.__freeze__()的实现。

开放问题

  • 我们是否应该为解冻冻结对象定义类似的协议?
  • 字典和集合是否应该自动冻结它们的可变键?
  • 我们是否应该支持“临时冻结”(也许使用名为__congeal__()的方法),类似于sets.Set中的__as_temporarily_immutable__()
  • 为了与sets.Set向后兼容,我们是否应该支持__as_immutable__()?或者__freeze__()是否应该重命名为__as_immutable__()

来源:https://github.com/python/peps/blob/main/peps/pep-0351.rst

最后修改:2025-09-16 00:19:46 GMT