冻结集就是冻结集。 冻结列表可以是元组。 冷冻字典会是什么?一个不可变的、可哈希的字典。

我猜它可能是collections.namedtuple之类的东西,但那更像是一个冻结的字典(一个半冻结的字典)。不是吗?

一个“frozendict”应该是一个冻结的字典,它应该有键,值,get等,并支持in, for等。

更新: 在这里:https://www.python.org/dev/peps/pep-0603


当前回答

namedtuple的主要缺点是需要在使用之前指定它,因此对于单一用例来说不太方便。

然而,有一种实用的变通方法可以用来处理许多此类情况。让我们假设你想有一个不可变的等价物如下dict:

MY_CONSTANT = {
    'something': 123,
    'something_else': 456
}

可以这样模拟:

from collections import namedtuple

MY_CONSTANT = namedtuple('MyConstant', 'something something_else')(123, 456)

甚至还可以编写一个辅助函数来实现自动化:

def freeze_dict(data):
    from collections import namedtuple
    keys = sorted(data.keys())
    frozen_type = namedtuple(''.join(keys), keys)
    return frozen_type(**data)

a = {'foo':'bar', 'x':'y'}
fa = freeze_dict(data)
assert a['foo'] == fa.foo

当然,这只适用于平面字典,但实现递归版本应该不会太难。

其他回答

奇怪的是,尽管我们有很少有用的frozenset,但仍然没有冻结映射。这个想法在PEP 416中被否决了——添加一个frozendict内置类型。这个想法可能会在后面的Python版本中重新讨论,请参阅PEP 603—向集合添加frozenmap类型。

所以Python 2的解决方案是:

def foo(config={'a': 1}):
    ...

这似乎仍是常态:

def foo(config=None):
    if config is None:
        config = {'a': 1}  # default config
    ...

在Python 3中,你可以这样做:

from types import MappingProxyType

default_config = {'a': 1}
DEFAULTS = MappingProxyType(default_config)

def foo(config=DEFAULTS):
    ...

现在,默认配置可以动态更新,但在您希望它不可变的地方保持不变,只需传递代理即可。

因此,default_config中的更改将按预期更新默认值,但不能写入映射代理对象本身。

诚然,它与“不可变的、可哈希的字典”不是一回事,但它可能是frozendict某些用例的体面替代品。

namedtuple的主要缺点是需要在使用之前指定它,因此对于单一用例来说不太方便。

然而,有一种实用的变通方法可以用来处理许多此类情况。让我们假设你想有一个不可变的等价物如下dict:

MY_CONSTANT = {
    'something': 123,
    'something_else': 456
}

可以这样模拟:

from collections import namedtuple

MY_CONSTANT = namedtuple('MyConstant', 'something something_else')(123, 456)

甚至还可以编写一个辅助函数来实现自动化:

def freeze_dict(data):
    from collections import namedtuple
    keys = sorted(data.keys())
    frozen_type = namedtuple(''.join(keys), keys)
    return frozen_type(**data)

a = {'foo':'bar', 'x':'y'}
fa = freeze_dict(data)
assert a['foo'] == fa.foo

当然,这只适用于平面字典,但实现递归版本应该不会太难。

在没有本地语言支持的情况下,您可以自己动手,也可以使用现有的解决方案。幸运的是,Python使得扩展它们的基本实现变得非常简单。

class frozen_dict(dict):
    def __setitem__(self, key, value):
        raise Exception('Frozen dictionaries cannot be mutated')

frozen_dict = frozen_dict({'foo': 'FOO' })
print(frozen['foo']) # FOO
frozen['foo'] = 'NEWFOO' # Exception: Frozen dictionaries cannot be mutated

# OR

from types import MappingProxyType

frozen_dict = MappingProxyType({'foo': 'FOO'})
print(frozen_dict['foo']) # FOO
frozen_dict['foo'] = 'NEWFOO' # TypeError: 'mappingproxy' object does not support item assignment

Freeze实现了可哈希的、类型提示的冻结集合(dict、list和set),并将递归地冻结你给他们的数据(如果可能的话)。

pip install frz

用法:

from freeze import FDict

a_mutable_dict = {
    "list": [1, 2],
    "set": {3, 4},
}

a_frozen_dict = FDict(a_mutable_dict)

print(repr(a_frozen_dict)) 
# FDict: {'list': FList: (1, 2), 'set': FSet: {3, 4}}

你可以使用utispie包装的冷冻液:

>>> from utilspie.collectionsutils import frozendict

>>> my_dict = frozendict({1: 3, 4: 5})
>>> my_dict  # object of `frozendict` type
frozendict({1: 3, 4: 5})

# Hashable
>>> {my_dict: 4}
{frozendict({1: 3, 4: 5}): 4}

# Immutable
>>> my_dict[1] = 5
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mquadri/workspace/utilspie/utilspie/collectionsutils/collections_utils.py", line 44, in __setitem__
    self.__setitem__.__name__, type(self).__name__))
AttributeError: You can not call '__setitem__()' for 'frozendict' object

根据文件:

frozendict(dict_obj):接受dict类型的obj并返回一个可哈希且不可变的dict