“Donmuş bir diksiyon” ne olurdu?


158
  • Dondurulmuş bir set bir frozensettir.
  • Dondurulmuş bir liste bir demet olabilir.
  • Donmuş bir diksiyon ne olurdu? Değişmez, yıkanabilir bir diksiyon.

Sanırım böyle bir şey olabilir collections.namedtuple, ama bu daha çok donmuş anahtarlar dikte (yarı donmuş dikt) gibi. Öyle değil mi?

Bir "frozendict" olması gereken, donmuş bir sözlük olmalıdır keys, values, getvb ve destek in, forvb

güncelleme:
* işte: https://www.python.org/dev/peps/pep-0603

Yanıtlar:


120

Python'un yerleşik bir frozendict tipi yoktur. Bunun çok sık faydalı olmayacağı ortaya çıkıyor (yine de muhtemelen olduğundan daha sık faydalı olacaktır frozenset).

Böyle bir tür istemenin en yaygın nedeni, işlevlerin hafızaya alınması bilinmeyen argümanlara sahip işlevleri çağırmasıdır. Bir diktenin yıkanabilir bir eşdeğerini (değerlerin yıkanabilir olduğu yerlerde) saklamak için en yaygın çözüm şudur tuple(sorted(kwargs.iteritems())).

Bu sıralamanın biraz deli olmamasına bağlıdır. Python, sıralamanın burada makul bir şeyle sonuçlanacağına olumlu söz veremez. (Ama başka bir şey vaat edemez, bu yüzden çok fazla terlemeyin.)


Kolayca bir dikte gibi çalışan bir tür sargı yapabilirsiniz. Şuna benzeyebilir

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

Harika çalışmalı:

>>> 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
İnsanların bu tür şeylerle ne düzeyde iplik güvenliği endişeleri olduğunu bilmiyorum, ancak bu açıdan __hash__yönteminiz biraz geliştirilebilir. Karmayı hesaplarken geçici bir değişken kullanın ve yalnızca self._hashson değere sahip olduğunuzda ayarlayın . Bu şekilde, ilk hesaplama yapılırken başka bir iş parçacığının karma elde edilmesi, yanlış bir değer elde etmek yerine basitçe fazladan hesaplama yapar.
Jeff DQ

22
@Jeff Kural olarak, her yerdeki tüm kodlar iş parçacığı için güvenli değildir ve bu kodu güvenle kullanabilmek için bazı senkronizasyon yapılarının etrafına sarmalısınız. Ayrıca, özel iplik güvenliği kavramı, garanti edilenden çok daha fazla olan nesne niteliği atamasının atomisitesine dayanır.
Devin Jeanpierre

9
@Anentropik, Bu hiç doğru değil.
Mike Graham

17
Dikkat edin: Bu "FrozenDict" mutlaka dondurulmuş değildir. Değişken bir listeyi değer olarak koymanızı engelleyecek hiçbir şey yoktur, bu durumda karma bir hata atar. Bu konuda mutlaka yanlış bir şey yoktur, ancak kullanıcılar farkında olmalıdır. Başka bir şey: Bu karma algoritması kötü seçilmiş, karma çarpışmalarına çok eğilimli. Örneğin {'a': 'b'}, {'b': 'a'} ve {'a': 1, 'b': 2} ile aynı hash'leri {'a': 2, 'ile aynı b ': 1}. Daha iyi bir seçim self._hash ^ = hash ((anahtar, değer)) olurdu
Steve Byrnes

6
Değişmez bir nesneye değiştirilebilir bir giriş eklerseniz, olası iki davranış, nesneyi oluştururken bir hata atmak veya nesneyi hash etmede bir hata atmaktır. Tuples ikincisini yapar, frozenset ilkini yapar. Kesinlikle, her şeyi dikkate alarak, ikinci yaklaşımı almak için iyi bir karar verdiğinizi düşünüyorum. Yine de, insanların FrozenDict ve frozenset'in benzer isimlere sahip olduğunu görebilir ve benzer şekilde davranmaları gerektiği sonucuna atlayabilirler. Bu yüzden insanları bu fark hakkında uyarmaya değer. :-)
Steve Byrnes

63

Merakla, python'da nadiren kullanışlı olmamıza rağmen frozenset, hala donmuş haritalama yok. Fikir PEP 416'da reddedildi - Bir frozendict yerleşik türü ekleyin . Fikir Python 3.9'da tekrar gözden geçirilebilir, bkz. PEP 603 - Koleksiyonlara dondurulmuş bir harita türü ekleme .

Python 2'nin buna çözümü:

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

Hala biraz topal gibi görünüyor:

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

Python3 size seçeneğine sahip bu :

from types import MappingProxyType

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

def foo(config=DEFAULTS):
    ...

Şimdi varsayılan yapılandırma olabilir dinamik olarak güncellenen, ancak bunu yerine vekil etrafında geçirerek değişmez olmak istediğim yer değişmez kalır edilebilir.

Dolayısıyla, değişikliklerdeki değişiklikler beklendiği gibi default_configgüncellenir DEFAULTS, ancak eşleme proxy nesnesinin kendisine yazamazsınız.

Kuşkusuz, "değişmez, yıkanabilir bir diksiyon" ile aynı şey değildir - ancak bir frozendict isteyebileceğimiz aynı türden kullanım durumları göz önüne alındığında iyi bir alternatiftir.


2
Proxy'yi bir modül değişkeninde saklamak için özel bir neden var mı? Neden sadece def foo(config=MappingProxyType({'a': 1})):? Örneğiniz yine de genel modifikasyona izin veriyor default_config.
jpmc26

Ayrıca, çift atamanın config = default_config = {'a': 1}bir yazım hatası olduğundan şüpheleniyorum .
jpmc26

21

Sözlüğün anahtarları ve değerlerinin kendileri değişmez olduğunu varsayarsak (örneğin, dizeler):

>>> 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

Bu, bir diktenin iyi, kanonik, değişmez bir temsilidir (çılgınca karşılaştırma davranışını sıralayan karışıklık).
Mike Graham

6
@devin: tam olarak kabul etti, ancak yazıma genellikle daha iyi bir yol olduğunu gösteren bir örnek vereyim.
msw

14
Daha da iyisi, anahtarların veya değerlerin tutarlı bir sıralamanın tanımlanmasını gerektirmeyen bir frozenset'e koymak olabilir.
asmeurer

8
Bununla ilgili tek bir sorun var: Artık eşlemeniz yok. İlk başta donmuş dikteye sahip olmanın tüm anlamı bu olurdu.
Mad Physicist

2
Bir dikteye geri dönerken bu yöntem gerçekten güzel. sadecedict(t)
codythecoder

12

Hayır fronzedict, ancak MappingProxyTypePython 3.3 ile standart kütüphaneye eklenenleri kullanabilirsiniz :

>>> 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})

uyarı ile:TypeError: can't pickle mappingproxy objects
Radu

Bunun fikrini seviyorum. Ben bir deneyeceğim.
Doug

Bu ilgili sorun MappingProxyTypehalen unhashable olduğunu.
Jab

10

İşte kullandığım kod. Ben frozenset alt sınıf. Bunun avantajları şunlardır.

  1. Bu gerçekten değişmez bir nesnedir. Gelecekteki kullanıcıların ve geliştiricilerin iyi davranışlarına dayanmak yok.
  2. Normal bir sözlük ile dondurulmuş bir sözlük arasında geçiş yapmak kolaydır. FrozenDict (orig_dict) -> dondurulmuş sözlük. dict (dondurulmuş_dict) -> düzenli dict.

21 Ocak 2015 Güncellemesi: 2014'te gönderdiğim orijinal kod parçası, eşleşen bir anahtarı bulmak için bir for-loop kullandı. İnanılmaz derecede yavaştı. Şimdi frozenset'in hash özelliklerinden yararlanan bir uygulamayı bir araya getirdim. Anahtar / değer çiftleri, __hash__ve __eq__işlevlerinin yalnızca anahtara dayandığı özel kaplarda saklanır . Bu kod, Ağustos 2014'te burada gönderdiğimden farklı olarak, resmi olarak birim test edildi.

MIT tarzı lisans.

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
Ayrıca, buraya göndererek CC BY-SA 3.0 altında lisansladığınızı unutmayın. En azından bu yaygın görüş . Bunun yasal dayanağını ilk kez kaydolduğunuzda bazı Şartlar ve Koşulları kabul ediyor.
Evgeni Sergeev

1
Beynimi kırmadan anahtar karmasını aramanın bir yolunu düşünmeye çalıştım. ItemAnahtarın karması olmak için hash'ı yeniden tanımlamak temiz bir hack!
clacke

Ne yazık ki, çalışma süresi diff(diff({key}))FrozenDict'in boyutunda hala doğrusal iken, normal durumda erişim süresi ortalama durumda sabittir.
Dennis

6

Ben böyle bir fonksiyon yazmak her zaman frozendict düşünüyorum:

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

6
Böyle bir yorum gördüğümde, bir yere battığımdan ve varsayılan olarak {} koyduğumdan eminim ve geri dönüp son yazdığım koduma bakıyorum.
Ryan Hiebert

1
Evet, herkesin er ya da geç karşılaştığı kötü bir şey.
Mark Visser

8
Daha kolay formülasyon:optional_dict_parm = optional_dict_parm or {}
Emmanuel

2
Bu durumda , bağımsız değişken için varsayılan değer olarak kullanabilirsiniz . types.MappingProxyType({})
GingerPlusPlus

@GingerPlusPlus bunu bir cevap olarak yazabilir misiniz?
jonrsharpe

5

Sen kullanabilir frozendictgelen utilspieolarak paketin:

>>> 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

Gereğince belgede :

frozendict (dict_obj) : Dikt türünün nesnesini kabul eder ve yıkanabilir ve değişmez bir diksiyon döndürür



3

Evet, bu benim ikinci cevabım, ama tamamen farklı bir yaklaşım. İlk uygulama saf python'daydı. Bu Cython'da. Cython modüllerini nasıl kullanacağınızı ve derleyeceğinizi biliyorsanız, bu normal bir sözlük kadar hızlıdır. Tek bir değeri almak için kabaca .04 ila .06 mikro-sn.

Bu "frozen_dict.pyx" dosyası

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']

İşte "setup.py" dosyası

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

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

Cython yüklüyse, yukarıdaki iki dosyayı aynı dizine kaydedin. Komut satırında bu dizine gidin.

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

Ve bitirmelisin.


3

Başlıca dezavantajı namedtuple, kullanılmadan önce belirtilmesi gerektiğidir, bu nedenle tek kullanımlık durumlar için daha az uygundur.

Bununla birlikte, bu tür birçok durumu ele almak için kullanılabilecek pratik bir geçici çözüm vardır. Aşağıdaki diktenin değişmez bir eşdeğerine sahip olmak istediğinizi varsayalım:

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

Bu şu şekilde taklit edilebilir:

from collections import namedtuple

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

Bunu otomatikleştirmek için yardımcı bir fonksiyon yazmak bile mümkündür:

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

Tabii ki bu sadece düz zorlamalar için çalışıyor, ancak özyinelemeli bir versiyon uygulamak çok zor olmamalı.


1
Diğer tuple cevabı ile aynı problem: getattr(fa, x)bunun yerine yapmanız gerekiyor , parmak uçlarınızda fa[x]hiçbir keysyöntem yok ve diğer tüm nedenler bir haritalamanın istenebilir.
Mad Physicist

1

sınıflara dict

vahşi (github) bu ​​desen görmek ve bundan bahsetmek istedim:

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

örnek kullanım:

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

Artıları

  • için destek get(), keys(), items()( iteritems()py2 üzerine) ve tüm güzellikler dictkutusunun dışarı bunları açıkça uygulamadan
  • dahili olarak kullanılır, dictbu da performans anlamına gelir ( dictCPython'da c ile yazılır)
  • zarif basit ve kara büyü yok
  • isinstance(my_frozen_dict, dict)True döndürür - python birçok paketin kullanımını ördek yazmayı teşvik etse de isinstance(), bu birçok tweak ve özelleştirmeyi kaydedebilir

Eksileri

  • herhangi bir alt sınıf bunu geçersiz kılabilir veya dahili olarak erişebilir (python'da bir şeyi gerçekten% 100 koruyamazsınız, kullanıcılarınıza güvenmeli ve iyi belgeler sağlamalısınız).
  • Hızı önemsiyorsanız, __hash__biraz daha hızlı yapmak isteyebilirsiniz .

Başka bir iş parçacığında bir hız karşılaştırması yaptım ve çıkıyor, geçersiz kılıyor__setitem__ ve miras dictbirçok alternatife göre inanılmaz derecede hızlı.
Torxed


0

Küresel sabitlikli bir şey olan bir şey için bir noktada sabit anahtarlara erişmem gerekiyordu ve böyle bir şeye karar verdim:

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

Gibi kullanın

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

UYARI: Oldukça ciddi dengesizlikler yaptığı için çoğu kullanım durumunda bunu önermiyorum.


Aşağıdakiler performans kıtlığı olmadan güçte eşit olacaktır. Ancak, bu sadece kabul edilen cevabın sadeleştirilmesi ... ``
Yuval

@Yuval bu cevaba eşdeğer değil. Yeni başlayanlar için api, başlaması gereken verilere ihtiyaç duyduğu için farklıdır. Bu aynı zamanda artık küresel olarak erişilebilir olmadığı anlamına da geliyor. Ayrıca, _data değiştirilirse, dönüş değeriniz değişir. Önemli ödünleşmeler olduğunun farkındayım - dediğim gibi, bunu çoğu kullanım için tavsiye etmiyorum.
Adverbly

-1

Ana dil desteğinin yokluğunda, bunu kendiniz yapabilir veya mevcut bir çözümü kullanabilirsiniz. Neyse ki Python, temel uygulamalarını genişletmeyi kolaylaştırır.

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 sınıfınız yıkanamaz
miracle173
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.