• Un conjunto estático es un frozenset.
  • Congelada lista podría ser una tupla.
  • ¿Qué sería de una congelado dict ser? Una inmutable, hashable dict.

Supongo que podría ser algo como collections.namedtuple, pero que se parece más a un congelado claves dict (una media congelado dict). ¿No es así?

Un «frozendict» debe ser congelado diccionario, se debe tener keys, values, get, etc., y apoyo in, for, etc.

actualización :

* no es : https://www.python.org/dev/peps/pep-0603

InformationsquelleAutor dugres | 2010-04-24

14 Comentarios

  1. 107

    Python no tiene incorporado un frozendict tipo. Resulta que este no sería útil demasiado a menudo (aunque aún así sería probablemente será útil más a menudo de lo que frozenset es).

    La razón más común para que quieres ese tipo es cuando memorización de las llamadas de función para las funciones con los argumentos desconocidos. La solución más común para almacenar un hashable equivalente de un diccionario (donde los valores se hashable) es algo así como tuple(sorted(kwargs.iteritems())).

    Esto depende de la clasificación de no ser un poco loco. Python no positivamente promesa de clasificación resultará en algo razonable aquí. (Pero no puedo prometer mucho más, así que no se preocupe demasiado.)


    Usted puede fácilmente hacer algún tipo de contenedor que funciona como un diccionario. Podría ser algo como

    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:
                self._hash = 0
                for pair in self.iteritems():
                    self._hash ^= hash(pair)
            return self._hash

    Se debe trabajar mucho:

    >>> 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'
    • Yo nunca he usado collections.Mapping, pero veo que usted no tiene funciones de comparación (eq, gt, lt, cmp, …). A menos que se proporcionan en la collections.Mapping, usted no necesita una función de hash. Python utiliza automáticamente el id del objeto como el hash de la clave.
    • proporciona __eq__ y __ne__ mixins, que queremos. Nosotros también quiero el hash. Los valores predeterminados de la identidad de comparación para la igualdad y la identificación para hash, significa que dos FrozenDict objetos que contienen los mismos datos no podría ser utilizado provechosamente como dict claves. He añadido el código de ejemplo que muestra cómo funciona esto muy bien.
    • No sé qué nivel de seguridad de los subprocesos personas que se preocupan con este tipo de cosas, pero en la que el respeto a su __hash__ método podría ser mejorado ligeramente. Simplemente usar una variable temporal a la hora de calcular el hash, y solo se self._hash una vez que tenga el valor final. De esa manera otro hilo obtener un hash mientras que el primero es el cálculo de simplemente hacer redundante de cálculo, en lugar de conseguir un valor incorrecto.
    • Como regla general, todo el código en todas partes no es thread-safe, y usted debe envolver alrededor de algunos de sincronización de estructuras con el fin de utilizar de forma segura en ese código. Además, su particular noción de hilo de seguridad se basa en la atomicidad de los atributos del objeto de cesión, que está lejos de estar garantizada.
    • volver a la clasificación… python garantiza el orden de clasificación será consistente, que para estos fines es una buena definición de «no loco’. el orden puede no ser significativa (por ejemplo alfabético) pero va a ser consistente.
    • Eso no es cierto en absoluto.
    • Python tipos de colección (dict, lista, set, etc, son thread-safe en todos los populares de implementaciones python (CPython, PyPy, IronPython, Jython) también todos los 4 las implementaciones han atómica objeto de asignación de atributos. Así que sí, en teoría está en lo correcto, pero en la práctica eso no importa. No subprocesos comportamiento puede ser sorprendente en un tipo de colecciones, y es fácil de remediar en este caso.
    • Advertencia: Este «FrozenDict» no es necesariamente congelado. No hay nada que le impida poner un mutable lista como un valor, en cuyo caso hash va a tirar un error. No hay nada necesariamente malo con eso, pero los usuarios deben ser conscientes de. Otra cosa: Este algoritmo de hashing está mal elegido, muy proclive a las colisiones de hash. Por ejemplo {‘a’:’b’} hash de la misma como {‘b’:’a’} y {‘a’:1, ‘b’:2} hash de la misma como {‘a’:2, ‘b’:1}. La mejor opción sería yo._hash ^= hash((clave, valor))
    • no Hay nada que le impida poner un mutable lista como un valor, en cuyo caso hash va a tirar un error. considero que es una característica–¿qué prefiere usted en su lugar? Lo mismo es cierto de otras colecciones inmutables, como tuplas.
    • Otra cosa: Este algoritmo de hashing está mal elegido, muy proclive a las colisiones de hash. Por ejemplo {‘a’:’b’} hash de la misma como {‘b’:’a’} y {‘a’:1, ‘b’:2} hash de la misma como {‘a’:2, ‘b’:1}. La mejor opción sería yo._hash ^= hash((clave, valor)) tienes razón, y el último ejemplo es particularmente convincente. He editado el post.
    • Si se agrega una variable de entrada en un objeto inmutable, los dos posibles comportamientos son para tirar un error en la creación del objeto, o producir un error en el hash del objeto. Tuplas hacer el último, frozenset realiza la primera. Definitivamente creo que tomé una buena decisión de tomar el último enfoque, todas las cosas consideradas. Sin embargo, creo que la gente puede ver que FrozenDict y frozenset tienen nombres similares, y saltar a la conclusión de que deben comportarse de manera similar. Así que creo que vale la pena advertir a la gente acerca de esta diferencia. 🙂
    • Supongo que se podría alterar las solicitudes y devuelve una copia del valor en el diccionario, en lugar del valor en sí mismo.
    • ¿por qué poner *args en __init__? no se que causa dict error de inicialización?
    • Me pase a través dict exactamente lo que usted llama FrozenDict con — errores no será causa de que no han sido causados por llamar dict.
    • Sé que este es un nicho de uso, pero no he encontrado tremendo el uso de frozensets en hacer matemáticas discretas, almacenamiento en caché de las funciones en las familias. Ellos proporcionan la búsqueda rápida, en comparación con el escaneo de un largo tupla, o incluso interseccion de una tupla ordenada. Son una de mis cosas favoritas en el idioma.
    • ¿Por qué no extender dict y reemplazar __setitem__ para generar un error? También añadir __hash__ de curso.
    • Yo personalmente he encontrado que frozensets son útiles para la descripción de aristas grafo en un gráfico. Sin ellos habría que comprobar constantemente con el fin de tuplas.
    • Yo estaría de acuerdo que frozendict no sería útil demasiado a menudo. Hemos cambiado un montón de lugares para utilizar frozendicts y quita un montón de errores. Por ejemplo, argumento por defecto bugs podría ser muy bien resuelto con def function(defaults=frozendict()). También thisngs como algoritmo el proceso de parametrización, el envío de dicts entre los componentes del sistema, el multithreading, sin cerraduras, etc. la caña de estar muy bien y lo hace de manera segura con frozendicts.
    • Para aquellos que necesitan rendimiento frozendict hay proyecto. Es la versión de FrozenDict implented con la ayuda de Cython.
    • no sería útil demasiado a menudo» – al contrario, es muy útil en la ciencia de datos, por ejemplo de grupo con los fragmentos de datos JSON. Yo uso el análogo de la funcionalidad en Wolfram Lenguaje, cuyos diccionarios se construyen utilizando intenta tan claves pueden ser mutables.

  2. 51

    Curiosamente, aunque tenemos la rara vez útil frozenset en python, no hay todavía ninguna congelados de asignación. La idea fue rechazada en PEP 416 — Agregar un frozendict builtin tipo. La idea puede ser revisado en Python 3.9, ver PEP 603 — la Adición de un frozenmap tipo de colecciones.

    Por lo que el python 2 solución:

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

    Parece ser todavía un poco cojo:

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

    En python3 usted tiene la opción de este:

    from types import MappingProxyType
    
    default_config = {'a': 1}
    DEFAULTS = MappingProxyType(default_config)
    
    def foo(config=DEFAULTS):
        ...

    Ahora la configuración por defecto puede ser actualizados de forma dinámica, sino que permanecen inmutables donde usted quiere que sea inmutable pasando en todo el proxy en su lugar.

    Por lo que los cambios en la default_config actualizará DEFAULTS como se esperaba, pero usted no puede escribir en la asignación de proxy objeto en sí mismo.

    Es cierto que no es la misma cosa como un «inmutable, hashable dict» – pero es un digno sustituto de dar el mismo tipo de casos de uso para los que queremos un frozendict.

    • ¿Hay alguna razón en particular para almacenar el proxy en un módulo de variable? ¿Por qué no def foo(config=MappingProxyType({'a': 1})):? Su ejemplo aún se permite la modificación global a través de default_config, demasiado.
    • También, sospecho que el doble de la asignación en la config = default_config = {'a': 1} es un error tipográfico.
  3. 18

    Asumiendo las claves y valores del diccionario de las mismas son inmutables (por ejemplo, cadenas), entonces:

    >>> 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
    • Esta es una buena canónica, inmutable representación de un diccionario (salvo loco comportamiento de la comparación de ensuciar la especie).
    • +1, pero nit: tuple(sorted(d.iteritems())) es más bonito.
    • se acordó en pleno, pero voy a dejar mi puesto de pie como un ejemplo de que a menudo hay una manera aún mejor.
    • Aún mejor sería ponerlo en un frozenset, que no requiere de las llaves o de los valores a tener una ordenación coherente definido.
    • Sólo un problema con esto: usted ya no tiene una asignación. Que sería el punto de tener la congelados dict en el primer lugar.
    • Este método es muy agradable al ir a un diccionario. simplemente dict(t)
    • Dependiendo exactamente lo que estamos haciendo, la clasificación puede ser innecesario.

  4. 12

    No hay fronzedict, pero se puede usar MappingProxyType que se agregó a la biblioteca estándar de Python 3.3:

    >>> 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})
    • con la salvedad de: TypeError: can't pickle mappingproxy objects
    • Me gusta la idea de este. Voy a darle una oportunidad.
  5. 9

    Aquí está el código que he estado usando. Yo subclases frozenset. Las ventajas de esto son los siguientes.

    1. Este es verdaderamente un objeto inmutable. No confiar en el buen comportamiento de los futuros usuarios y desarrolladores.
    2. Es fácil de convertir de ida y vuelta entre un diccionario corriente y congelado diccionario. FrozenDict(orig_dict) –> congelado diccionario. dict(frozen_dict) –> regular dict.

    Actualización 21 de enero de 2015: el original de La pieza de código que he publicado en 2014 se utiliza un bucle para encontrar una clave que coinciden. Que era increíblemente lento. Ahora he creado una aplicación que aprovecha la ventaja de frozenset del hash características. Los pares clave-valor son almacenados en contenedores especiales donde la __hash__ y __eq__ funciones se basan en la llave. Este código también ha sido formalmente la unidad probada, a diferencia de lo que he publicado aquí en agosto de 2014.

    MIT-estilo de licencia.

    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)
    • Tenga en cuenta que usted también ha concedido una licencia en virtud de CC-BY-SA 3.0, mediante la publicación aquí. Al menos esa es la la visión prevalente. Supongo que la base jurídica para la que se está aceptando algunos T&Cs cuando se inscribió.
    • Se me rompió mi cerebro tratando de pensar en una manera de buscar la clave hash sin un diccionario. Redefiniendo el hash de la Item a ser el hash de la clave es un buen hack!
    • Por desgracia, el tiempo de ejecución de diff(diff({key})) todavía es lineal en el tamaño de la FrozenDict, mientras que la regular dict el tiempo de acceso es constante en el caso promedio.
  6. 5

    Creo que de frozendict cada vez que tengo que escribir una función como esta:

    def do_something(blah, optional_dict_parm=None):
    if optional_dict_parm is None:
    optional_dict_parm = {}
    • Cada vez que veo un comentario como este estoy seguro de que me la pata en algún punto y poner {} como un defecto, y volver atrás y mirar a mi recientemente código escrito.
    • Sí, es una desagradable gotcha que todo el mundo se ejecuta en, más pronto o más tarde.
    • Más fácil formulación: optional_dict_parm = optional_dict_parm or {}
    • En este caso se puede usar types.MappingProxyType({}) como valor por defecto para el argumento.
    • se podría escribir como una respuesta?
    • parece como @wim ya lo hizo.
    • sí, llegó hasta en otra parte!

  7. 4

    Puede utilizar frozendict de utilspie paquete como:

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

    Como por la documento:

    frozendict(dict_obj): Acepta obj de dict tipo y devuelve un hashable e inmutable dict

  8. 3

    Sí, esta es mi segunda respuesta, pero es un enfoque completamente diferente. La primera aplicación fue en python puro. Este es en Cython. Si usted sabe cómo usar y compilar Cython módulos, esto es tan rápido como un diccionario. Aproximadamente .04 a .06 micro-seg para recuperar un único valor.

    Este es el archivo «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']

    Aquí esta el archivo «setup.py»

    from distutils.core import setup
    from Cython.Build import cythonize
    setup(
    ext_modules = cythonize('frozen_dict.pyx')
    )

    Si usted tiene Cython instalado, guarde los dos archivos en el mismo directorio. Mover a ese directorio en la línea de comandos.

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

    Y que se debe hacer.

  9. 3

    La principal desventaja de namedtuple es que debe ser especificado antes de usarlo, por lo que es menos conveniente para el uso único de los casos.

    Sin embargo, existe una solución que se puede utilizar para manejar muchos de esos casos. Digamos que usted quiere tener una inmutable equivalente de la siguiente dict:

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

    Esto puede ser emulado como este:

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

    Es posible escribir una función auxiliar para automatizar este:

    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

    Por supuesto, esto sólo funciona para los planos dicts, pero no debería ser demasiado difícil de implementar una versión recursiva.

    • Mismo problema que con la otra tupla respuesta: usted tiene que hacer getattr(fa, x) en lugar de fa[x], no keys método en sus extremidades del dedo, y todas las otras razones de mapeo puede ser deseable.
  10. 0

    Subclases dict

    veo este patrón en la naturaleza (github) y quería mencionar es:

    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

    ejemplo de uso:

    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

    Pros

    • apoyo para get(), keys(), items() (iteritems() en py2) y todos los extras de dict fuera de la caja sin explícitamente la aplicación de ellos
    • utiliza internamente dict lo que significa que el rendimiento (dict está escrito en c en CPython)
    • elegante, simple y sin magia negra
    • isinstance(my_frozen_dict, dict) devuelve True – aunque python anima duck-typing el número de paquetes que utiliza isinstance(), esto puede ahorrar muchos ajustes y personalizaciones

    Contras

    • cualquier subclase puede reemplazar este acceso o internamente (usted no puede realmente el 100% de proteger algo en python, debes confiar en tus usuarios y proporcionar la documentación).
    • si la atención a la velocidad, usted puede querer hacer __hash__ un poco más rápido.
  11. 0

    En la ausencia de compatibilidad de idioma, usted puede hacerlo usted mismo o utilizar una solución existente. Afortunadamente, Python hace que sea increíblemente fácil de extender fuera de su base de implementaciones.

    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
  12. 0

    Necesitaba para acceso fijo claves para algo en un momento por algo que era una especie de mundial constanty tipo de cosas y me decidí por algo como esto:

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

    Utilizar como

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

    ADVERTENCIA: yo no recomiendo esto para la mayoría de los casos de uso, ya que hace algunos bastante graves desventajas.

    • El siguiente sería igual en el poder sin que el rendimiento scarifices. Sin embargo, esto es sólo una simplificación de la aceptó responder… « clase FrozenDict: def __init__(self, datos): sí._data = datos def __getitem__(self, clave): return self._data[clave] «
    • la respuesta es no equivalente. Para empezar, la api es diferente, ya que las necesidades de datos para init. Esto también implica que ya no es globalmente accesible. Además, si _data está mutado, de su valor de retorno de cambios. Soy consciente de que existen importantes concesiones – como he dicho, yo no recomiendo esto para la mayoría de los casos de uso.

Dejar respuesta

Please enter your comment!
Please enter your name here