"동결 된 dict"은 무엇입니까?


158
  • 고정 세트는 고정 세트입니다.
  • 고정 된 목록은 튜플 일 수 있습니다.
  • 얼어 붙은 구술은 무엇입니까? 불변의 해시 가능한 dict.

나는 그것이 같은 것일 수 있다고 생각 collections.namedtuple하지만, 그것은 고정 키 dict (반 냉동 dict)와 비슷합니다. 그렇지 않습니까?

A "frozendict는"이 있어야한다, 냉동 사전되어야한다 keys, values, get, 등 및 지원 in, for

업데이트 :
* 있습니다 : https://www.python.org/dev/peps/pep-0603

답변:


120

파이썬에는 내장 된 dictdict 유형이 없습니다. 이것은 너무 자주 유용하지 않을 것입니다 (아마도 여전히보다 자주 유용 할 것 frozenset입니다).

이러한 유형을 원하는 가장 일반적인 이유는 함수를 메모리에 저장하면 알 수없는 인수를 가진 함수를 호출 할 때입니다. dict과 같은 해시 가능 값을 저장하는 가장 일반적인 솔루션 (값이 해시 가능)은 다음과 같습니다 tuple(sorted(kwargs.iteritems())).

정렬이 약간 미쳤지 않은지에 따라 다릅니다. 파이썬은 정렬이 여기에 합리적인 결과를 가져올 것이라고 긍정적으로 약속 할 수 없습니다. (그러나 그것은 다른 많은 것을 약속 할 수 없으므로 너무 땀을 흘리지 마십시오.)


dict처럼 작동하는 래퍼를 쉽게 만들 수 있습니다. 다음과 같이 보일 수 있습니다.

import collections

class FrozenDict(collections.Mapping):
    """Don't forget the docstrings!!"""

    def __init__(self, *args, **kwargs):
        self._d = dict(*args, **kwargs)
        self._hash = None

    def __iter__(self):
        return iter(self._d)

    def __len__(self):
        return len(self._d)

    def __getitem__(self, key):
        return self._d[key]

    def __hash__(self):
        # It would have been simpler and maybe more obvious to 
        # use hash(tuple(sorted(self._d.iteritems()))) from this discussion
        # so far, but this solution is O(n). I don't know what kind of 
        # n we are going to run into, but sometimes it's hard to resist the 
        # urge to optimize when it will gain improved algorithmic performance.
        if self._hash is None:
            hash_ = 0
            for pair in self.items():
                hash_ ^= hash(pair)
            self._hash = hash_
        return self._hash

잘 작동해야합니다.

>>> x = FrozenDict(a=1, b=2)
>>> y = FrozenDict(a=1, b=2)
>>> x is y
False
>>> x == y
True
>>> x == {'a': 1, 'b': 2}
True
>>> d = {x: 'foo'}
>>> d[y]
'foo'

7
사람들이 이런 종류의 스레드 안전에 대해 어떤 수준의 스레드 안전을 걱정하는지 모르겠지만 그 점에서 귀하의 __hash__방법이 약간 향상 될 수 있습니다. 해시를 계산할 때 임시 변수를 사용 self._hash하고 최종 값을 얻은 후에 만 설정 하십시오. 그렇게하면 첫 번째 계산하는 동안 다른 스레드가 해시를 얻는 것은 잘못된 값을 얻는 대신 단순히 중복 계산을 수행합니다.
Jeff DQ

22
@Jeff 원칙적으로 모든 코드는 스레드로부터 안전하지 않으므로 해당 코드를 안전하게 사용하려면 일부 동기화 구조를 감싸 야합니다. 또한 스레드 안전에 대한 특정 개념은 보장되지 않은 객체 속성 할당의 원자성에 의존합니다.
Devin Jeanpierre 2018 년

9
@Anentropic, 그건 사실이 아닙니다.
Mike Graham

17
경고 :이 "FrozenDict"가 반드시 동결 된 것은 아닙니다. 변경 가능한 목록을 값으로 설정하는 것을 막을 방법은 없습니다.이 경우 해싱에서 오류가 발생합니다. 반드시 문제는 없지만 사용자는 알고 있어야합니다. 또 다른 한 가지 :이 해싱 알고리즘은 잘못 선택되어 해시 충돌이 발생하기 쉽습니다. 예를 들어 { 'a': 'b'}는 { 'b': 'a'}와 동일한 해시 및 { 'a': 1, 'b': 2}는 { 'a': 2, '와 동일한 해시 b ': 1}. 더 나은 선택은 self._hash ^ = hash ((key, value))입니다.
Steve Byrnes

6
변경 불가능한 객체에 변경 가능한 항목을 추가하는 경우 가능한 두 가지 동작은 객체를 만들 때 오류를 발생 시키거나 객체를 해시 할 때 오류를 발생시키는 것입니다. 튜플은 후자를 수행하고 고정 된 것은 전자를 수행합니다. 나는 당신이 후자의 접근법을 고려하기로 결정했다고 생각합니다. 그럼에도 불구하고 사람들은 FrozenDict와 frozenset의 이름이 비슷한 것을 볼 수 있으며 비슷한 방식으로 동작해야한다는 결론에 도달 할 수 있다고 생각합니다. 이 차이에 대해 사람들에게 경고 할 가치가 있다고 생각합니다. :-)
Steve Byrnes

63

흥미롭게도 frozenset파이썬 에는 거의 유용하지 않지만 여전히 얼어 붙은 매핑은 없습니다. 이 아이디어는 PEP 416 에서 거부되었습니다 . 고정 된 내장 유형을 추가하십시오 . 이 아이디어는 Python 3.9에서 다시 확인할 수 있습니다. PEP 603-컬렉션에 고정 된 맵 유형 추가를 참조하십시오 .

따라서 파이썬 2 솔루션은 다음과 같습니다.

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

여전히 다소 절름발이 인 것 같습니다 :

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

python3에는 다음과 같은 옵션 이 있습니다 .

from types import MappingProxyType

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

def foo(config=DEFAULTS):
    ...

이제 기본 구성 동적으로 업데이트 수 있지만 대신 프록시를 전달하여 변경할 수없는 위치를 변경할 수 없습니다.

따라서의 변경 사항은 예상대로 default_config업데이트 DEFAULTS되지만 매핑 프록시 객체 자체에는 쓸 수 없습니다.

분명히 그것은 "불변의, 해시 가능한 dict"와 같은 것은 아니지만-우리가 고정 된 dict를 원할 수도있는 같은 종류의 유스 케이스를 감안할 때 적절한 대체물입니다.


2
프록시를 모듈 변수에 저장해야하는 특별한 이유가 있습니까? 왜 안돼 def foo(config=MappingProxyType({'a': 1})):? 귀하의 예는 여전히을 통해 전역 수정을 허용 default_config합니다.
jpmc26

또한 이중 할당 config = default_config = {'a': 1}이 오타 라고 생각합니다 .
jpmc26

21

사전의 키와 값을 변경할 수 없다고 가정하면 (예 : 문자열) :

>>> d
{'forever': 'atones', 'minks': 'cards', 'overhands': 'warranted', 
 'hardhearted': 'tartly', 'gradations': 'snorkeled'}
>>> t = tuple((k, d[k]) for k in sorted(d.keys()))
>>> hash(t)
1524953596

이것은 좋은 정식, 불변의 dict 표현입니다 (정렬 한 혼란스러운 행동을 금지합니다).
Mike Graham

6
@ devin : 완전히 동의했지만 더 나은 방법이 종종 있다는 것을 예로 들겠습니다.
msw

14
키나 값이 일관된 순서를 갖도록 요구하지 않는 고정 된 세트에 넣는 것이 더 좋습니다.
asmeurer

7
이 문제는 단 하나의 문제입니다. 더 이상 매핑이 없습니다. 그것은 처음에 얼어 붙은 dict를 갖는 요점입니다.
미친 물리학 자

2
이 방법은 dict으로 돌아갈 때 정말 좋습니다. 간단히dict(t)
codythecoder 2

12

는 없지만 Python 3.3으로 표준 라이브러리에 추가 된 것을 fronzedict사용할 수 있습니다 MappingProxyType.

>>> from types import MappingProxyType
>>> foo = MappingProxyType({'a': 1})
>>> foo
mappingproxy({'a': 1})
>>> foo['a'] = 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'mappingproxy' object does not support item assignment
>>> foo
mappingproxy({'a': 1})

경고와 함께 :TypeError: can't pickle mappingproxy objects
Radu

나는 이것의 아이디어를 좋아한다. 나는 그것을 시도 할 것입니다.
Doug

10

내가 사용한 코드는 다음과 같습니다. 나는 고정 세트를 서브 클래 싱했다. 이것의 장점은 다음과 같습니다.

  1. 이것은 정말 불변의 객체입니다. 미래의 사용자와 개발자의 좋은 행동에 의존하지 않습니다.
  2. 일반 사전과 고정 된 사전간에 쉽게 전환 할 수 있습니다. FrozenDict (orig_dict)-> 고정 된 사전. dict (frozen_dict)-> 일반 dict.

2015 년 1 월 21 일 업데이트 : 2014 년에 게시 한 원래 코드는 for-loop를 사용하여 일치하는 키를 찾았습니다. 그것은 엄청나게 느렸다. 이제 frozenset의 해싱 기능을 활용하는 구현을 구성했습니다. 키-값 쌍은 __hash____eq__기능이 키만 기반으로하는 특수 컨테이너에 저장 됩니다. 이 코드는 2014 년 8 월에 게시 한 것과 달리 공식적으로 단위 테스트를 거쳤습니다.

MIT 스타일 라이센스.

if 3 / 2 == 1:
    version = 2
elif 3 / 2 == 1.5:
    version = 3

def col(i):
    ''' For binding named attributes to spots inside subclasses of tuple.'''
    g = tuple.__getitem__
    @property
    def _col(self):
        return g(self,i)
    return _col

class Item(tuple):
    ''' Designed for storing key-value pairs inside
        a FrozenDict, which itself is a subclass of frozenset.
        The __hash__ is overloaded to return the hash of only the key.
        __eq__ is overloaded so that normally it only checks whether the Item's
        key is equal to the other object, HOWEVER, if the other object itself
        is an instance of Item, it checks BOTH the key and value for equality.

        WARNING: Do not use this class for any purpose other than to contain
        key value pairs inside FrozenDict!!!!

        The __eq__ operator is overloaded in such a way that it violates a
        fundamental property of mathematics. That property, which says that
        a == b and b == c implies a == c, does not hold for this object.
        Here's a demonstration:
            [in]  >>> x = Item(('a',4))
            [in]  >>> y = Item(('a',5))
            [in]  >>> hash('a')
            [out] >>> 194817700
            [in]  >>> hash(x)
            [out] >>> 194817700
            [in]  >>> hash(y)
            [out] >>> 194817700
            [in]  >>> 'a' == x
            [out] >>> True
            [in]  >>> 'a' == y
            [out] >>> True
            [in]  >>> x == y
            [out] >>> False
    '''

    __slots__ = ()
    key, value = col(0), col(1)
    def __hash__(self):
        return hash(self.key)
    def __eq__(self, other):
        if isinstance(other, Item):
            return tuple.__eq__(self, other)
        return self.key == other
    def __ne__(self, other):
        return not self.__eq__(other)
    def __str__(self):
        return '%r: %r' % self
    def __repr__(self):
        return 'Item((%r, %r))' % self

class FrozenDict(frozenset):
    ''' Behaves in most ways like a regular dictionary, except that it's immutable.
        It differs from other implementations because it doesn't subclass "dict".
        Instead it subclasses "frozenset" which guarantees immutability.
        FrozenDict instances are created with the same arguments used to initialize
        regular dictionaries, and has all the same methods.
            [in]  >>> f = FrozenDict(x=3,y=4,z=5)
            [in]  >>> f['x']
            [out] >>> 3
            [in]  >>> f['a'] = 0
            [out] >>> TypeError: 'FrozenDict' object does not support item assignment

        FrozenDict can accept un-hashable values, but FrozenDict is only hashable if its values are hashable.
            [in]  >>> f = FrozenDict(x=3,y=4,z=5)
            [in]  >>> hash(f)
            [out] >>> 646626455
            [in]  >>> g = FrozenDict(x=3,y=4,z=[])
            [in]  >>> hash(g)
            [out] >>> TypeError: unhashable type: 'list'

        FrozenDict interacts with dictionary objects as though it were a dict itself.
            [in]  >>> original = dict(x=3,y=4,z=5)
            [in]  >>> frozen = FrozenDict(x=3,y=4,z=5)
            [in]  >>> original == frozen
            [out] >>> True

        FrozenDict supports bi-directional conversions with regular dictionaries.
            [in]  >>> original = {'x': 3, 'y': 4, 'z': 5}
            [in]  >>> FrozenDict(original)
            [out] >>> FrozenDict({'x': 3, 'y': 4, 'z': 5})
            [in]  >>> dict(FrozenDict(original))
            [out] >>> {'x': 3, 'y': 4, 'z': 5}   '''

    __slots__ = ()
    def __new__(cls, orig={}, **kw):
        if kw:
            d = dict(orig, **kw)
            items = map(Item, d.items())
        else:
            try:
                items = map(Item, orig.items())
            except AttributeError:
                items = map(Item, orig)
        return frozenset.__new__(cls, items)

    def __repr__(self):
        cls = self.__class__.__name__
        items = frozenset.__iter__(self)
        _repr = ', '.join(map(str,items))
        return '%s({%s})' % (cls, _repr)

    def __getitem__(self, key):
        if key not in self:
            raise KeyError(key)
        diff = self.difference
        item = diff(diff({key}))
        key, value = set(item).pop()
        return value

    def get(self, key, default=None):
        if key not in self:
            return default
        return self[key]

    def __iter__(self):
        items = frozenset.__iter__(self)
        return map(lambda i: i.key, items)

    def keys(self):
        items = frozenset.__iter__(self)
        return map(lambda i: i.key, items)

    def values(self):
        items = frozenset.__iter__(self)
        return map(lambda i: i.value, items)

    def items(self):
        items = frozenset.__iter__(self)
        return map(tuple, items)

    def copy(self):
        cls = self.__class__
        items = frozenset.copy(self)
        dupl = frozenset.__new__(cls, items)
        return dupl

    @classmethod
    def fromkeys(cls, keys, value):
        d = dict.fromkeys(keys,value)
        return cls(d)

    def __hash__(self):
        kv = tuple.__hash__
        items = frozenset.__iter__(self)
        return hash(frozenset(map(kv, items)))

    def __eq__(self, other):
        if not isinstance(other, FrozenDict):
            try:
                other = FrozenDict(other)
            except Exception:
                return False
        return frozenset.__eq__(self, other)

    def __ne__(self, other):
        return not self.__eq__(other)


if version == 2:
    #Here are the Python2 modifications
    class Python2(FrozenDict):
        def __iter__(self):
            items = frozenset.__iter__(self)
            for i in items:
                yield i.key

        def iterkeys(self):
            items = frozenset.__iter__(self)
            for i in items:
                yield i.key

        def itervalues(self):
            items = frozenset.__iter__(self)
            for i in items:
                yield i.value

        def iteritems(self):
            items = frozenset.__iter__(self)
            for i in items:
                yield (i.key, i.value)

        def has_key(self, key):
            return key in self

        def viewkeys(self):
            return dict(self).viewkeys()

        def viewvalues(self):
            return dict(self).viewvalues()

        def viewitems(self):
            return dict(self).viewitems()

    #If this is Python2, rebuild the class
    #from scratch rather than use a subclass
    py3 = FrozenDict.__dict__
    py3 = {k: py3[k] for k in py3}
    py2 = {}
    py2.update(py3)
    dct = Python2.__dict__
    py2.update({k: dct[k] for k in dct})

    FrozenDict = type('FrozenDict', (frozenset,), py2)

1
CC BY-SA 3.0에 따라 여기에 게시하여 라이센스를 부여했습니다. 적어도 그것은 일반적인 견해 입니다. 처음 가입 할 때 법적 근거가 일부 T & C에 동의하는 것 같습니다.
Evgeni Sergeev

1
나는 dict없이 키 해시를 찾는 방법을 생각하려고 내 두뇌를 깨뜨렸다. Item키의 해시가되도록 해시를 재정의하는 것은 깔끔한 해킹입니다!
clacke

불행히도, 실행 시간은 diff(diff({key}))FrozenDict의 크기와 선형이지만, 일반적인 경우 dict 액세스 시간은 일정합니다.
Dennis

6

다음과 같은 함수를 작성할 때마다 frozendict를 생각합니다.

def do_something(blah, optional_dict_parm=None):
    if optional_dict_parm is None:
        optional_dict_parm = {}

6
이와 같은 주석을 볼 때마다 나는 어딘가를 망쳐 놓고 {}을 기본값으로 설정하고 되돌아 가서 최근에 작성한 코드를 봅니다.
Ryan Hiebert

1
예, 모두가 조만간 마주 치게되는 것은 불쾌한 일입니다.
Mark Visser

8
더 쉬운 공식화 :optional_dict_parm = optional_dict_parm or {}
Emmanuel

2
이 경우 인수의 기본값으로 사용할 수 있습니다 . types.MappingProxyType({})
GingerPlusPlus

@GingerPlusPlus 답변으로 작성할 수 있습니까?
jonrsharpe 2016 년

5

당신은 사용할 수 있습니다 frozendict에서 utilspie같은 패키지 :

>>> 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를 반환합니다.



3

네, 이것은 두 번째 대답이지만 완전히 다른 접근법입니다. 첫 번째 구현은 순수한 파이썬이었습니다. 이것은 Cython에 있습니다. Cython 모듈을 사용하고 컴파일하는 방법을 알고 있다면 일반 사전만큼 빠릅니다. 단일 값을 검색하는 데 약 .04 ~ .06 마이크로 초

파일 "frozen_dict.pyx"

import cython
from collections import Mapping

cdef class dict_wrapper:
    cdef object d
    cdef int h

    def __init__(self, *args, **kw):
        self.d = dict(*args, **kw)
        self.h = -1

    def __len__(self):
        return len(self.d)

    def __iter__(self):
        return iter(self.d)

    def __getitem__(self, key):
        return self.d[key]

    def __hash__(self):
        if self.h == -1:
            self.h = hash(frozenset(self.d.iteritems()))
        return self.h

class FrozenDict(dict_wrapper, Mapping):
    def __repr__(self):
        c = type(self).__name__
        r = ', '.join('%r: %r' % (k,self[k]) for k in self)
        return '%s({%s})' % (c, r)

__all__ = ['FrozenDict']

다음은 "setup.py"파일입니다

from distutils.core import setup
from Cython.Build import cythonize

setup(
    ext_modules = cythonize('frozen_dict.pyx')
)

Cython을 설치 한 경우 위의 두 파일을 동일한 디렉토리에 저장하십시오. 명령 행에서 해당 디렉토리로 이동하십시오.

python setup.py build_ext --inplace
python setup.py install

그리고 당신은해야합니다.


3

가장 큰 단점 namedtuple은 사용하기 전에 지정해야하므로 일회용 사례에서는 덜 편리하다는 것입니다.

그러나 많은 경우를 처리하는 데 사용할 수있는 실질적인 해결 방법이 있습니다. 다음과 같은 내용을 변경할 수 없다고 가정 해 봅시다.

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

물론 이것은 단순한 dicts에 대해서만 작동하지만 재귀 버전을 구현하는 것은 어렵지 않아야합니다.


1
같은 문제는 다른 튜플 응답과 같이 당신이해야 할 getattr(fa, x)대신 fa[x], 더 keys당신의 손가락 끝을 방법, 그리고 다른 모든 이유가 매핑이 바람직 할 수 있습니다.
미친 물리학 자

1

서브 클래 싱 dict

나는 야생 (github) 에서이 패턴을보고 그것을 언급하고 싶었다 :

class FrozenDict(dict):
    def __init__(self, *args, **kwargs):
        self._hash = None
        super(FrozenDict, self).__init__(*args, **kwargs)

    def __hash__(self):
        if self._hash is None:
            self._hash = hash(tuple(sorted(self.items())))  # iteritems() on py2
        return self._hash

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

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

사용법 예 :

d1 = FrozenDict({'a': 1, 'b': 2})
d2 = FrozenDict({'a': 1, 'b': 2})
d1.keys() 
assert isinstance(d1, dict)
assert len(set([d1, d2])) == 1  # hashable

찬성

  • 에 대한 지원 get(), keys(), items()( iteritems()py2에)과의 모든 케이크 dict상자 밖으로 명시 적으로 구현하지 않고
  • 내부적 dict으로 사용하여 성능을 의미합니다 ( dictCPython에서 c로 작성 됨)
  • 우아하고 단순하며 흑 마법 없음
  • isinstance(my_frozen_dict, dict)파이썬은 많은 패키지 사용을 오리 타이핑 하도록 권장하지만 isinstance()많은 조정 및 사용자 정의를 저장할 수 있습니다

단점

  • 모든 서브 클래스는 이것을 재정의하거나 내부적으로 액세스 할 수 있습니다 (파이썬에서 무언가를 실제로 100 % 보호 할 수는 없으며 사용자를 신뢰하고 좋은 문서를 제공해야합니다).
  • 속도를 걱정한다면 __hash__조금 더 빨리 만들고 싶을 수도 있습니다 .

다른 스레드 에서 속도 비교를 수행했으며 많은 대안에 비해 재정의 __setitem__및 상속 dict이 엄청나게 빠릅니다.
Torxed


0

나는 일종의 전역 적으로 일정한 종류의 무언가를 위해 한 시점에서 고정 키에 액세스해야했고 다음과 같이 설정했습니다.

class MyFrozenDict:
    def __getitem__(self, key):
        if key == 'mykey1':
            return 0
        if key == 'mykey2':
            return "another value"
        raise KeyError(key)

처럼 사용

a = MyFrozenDict()
print(a['mykey1'])

경고 : 대부분의 유스 케이스에는 약간의 절충이 있으므로 권장하지 않습니다.


성능 저하없이 다음과 같은 성능을 얻을 수 있습니다. 그러나 이것은 허용되는 대답을 단순화 한 것입니다.```class FrozenDict : def __init __ (self, data) : self._data = data def __getitem __ (self, key) : return self._data [key]`` `
Yuval

그 대답은 동일하지 않습니다. 초보자의 경우 API는 초기화 해야하는 데이터가 필요하므로 다릅니다. 또한 더 이상 전 세계적으로 액세스 할 수 없습니다. 또한 _data가 변경되면 반환 값이 변경됩니다. 필자는 말했듯이 대부분의 사용 사례에서는 이것을 권장하지 않습니다.
Adverbly

-1

자국어 지원이없는 경우 직접 수행하거나 기존 솔루션을 사용할 수 있습니다. 다행스럽게도 파이썬은 기본 구현을 확장하는 것을 간단하게 만듭니다.

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

frozen_dict 클래스는 해시 할 수 없습니다
기적 173
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.