Crear Defaultdict de Defaultdict en Python

Olorunfemi Akinlua 21 junio 2023
Crear Defaultdict de Defaultdict en Python

Python tiene contenedores incorporados como dict, list, set y tuple, que tienen una ideología de propósito general. Para ampliar o mejorar estos contenedores de uso general, Python proporciona un módulo que introduce tipos de datos de contenedores especializados denominados Colecciones de Python.

Uno de estos tipos de datos de contenedores especializados es defaultdict, que es una excelente alternativa (y una subclase) a los diccionarios predeterminados de Python (dict). Con defaultdict, puede proporcionar una función de fábrica para proporcionar valores faltantes (en lugar de una excepción o mensaje KeyError).

Entonces, si la clave no está presente en el diccionario, se llama a la función factory y devuelve un valor en lugar de generar una excepción KeyError.

Usar defaultdict puede ser relativamente simple, pero trabajar con defaultdict de defaultdict puede ser confuso. Este artículo explicará cómo crear defaultdict de defaultdict sin causar ningún error y cómo ocurren sus operaciones intrínsecas.

Use lambda para crear Defaultdict de Defaultdict en Python

Para hacer uso de las colecciones de Python e inherentemente defaultdict, puede importar el módulo de colección usando la expresión de Python:

from collections import defaultdict

Tenga en cuenta que defaultdict es una subclase de la clase dict, que puede comprobar la siguiente expresión de Python:

issubclass(defaultdict, dict)

Producción :

True

Con dict, cuando una clave que no existe se pasa al diccionario, activa el método __missing__, que contiene un atributo default_factory establecido en Ninguno, y por lo tanto genera una excepción KeyError. Sin embargo, con default_dict, cuando una clave que no existe se pasa al diccionario, activa el atributo default_factory del método __missing__, que contiene una fábrica que devuelve un valor predeterminado.

Por ejemplo, podemos tener un diccionario defaultdict que contenga la función factory, list, que devuelve una lista vacía cuando se pasa una clave inexistente.

from collections import defaultdict

ddict = defaultdict(list)
print(ddict["one"])

Producción :

[]

Aunque ddict no tiene la clave uno, devuelve el valor de una lista vacía porque se pasa la función fábrica. Incluso crea la clave después de tal expresión.

from collections import defaultdict

ddict = defaultdict(list)
print(ddict["one"])
print(ddict["two"].append(1))

print(ddict)

Producción :

[]
defaultdict(<class 'list'>, {'one': [], 'two': [1]})

Entonces, después de las sentencias ddict["one"] y ddict["two"].append(1), crea las claves respectivas y un valor correspondiente basado en la función list. Para la segunda declaración de Python, crea la lista vacía basada en la función de atributo default_factory y luego le agrega el valor 1.

La agrupación típica de valores dentro de un tipo de datos defaultdict se puede manejar de manera diferente que con un tipo de datos dict.

sentence = "the man loves oranges, but also cares a great deal about apples"

letterStore = dict()

for i in sentence:
    if k not in letterStore:
        letterStore[i] = 1
        continue
    letterStore[i] += 1

print(letterStore.items())

Producción :

dict_items([('t', 4), ('h', 1), ('e', 7), (' ', 11), ('m', 1), ('a', 9), ('n', 2), ('l', 4), ('o', 4), ('v', 1), ('s', 5), ('r', 3), ('g', 2), (',', 1), ('b', 2), ('u', 2), ('c', 1), ('d', 1), ('p', 2)])

La agrupación anterior de las letras se puede hacer fácilmente con el uso de defaultdict en su lugar. En lugar de tener el bloque de código que verifica si las letras ya están en el enlace letterStore para crear una numeración inicial, podemos usar defaultdict para lograr esto con una función factory - int.

from collections import defaultdict

sentence = "the man loves oranges, but also cares a great deal about apples"

letterStore = defaultdict(int)

for i in sentence:
    letterStore[i] += 1

print(letterStore.items())

Producción :

dict_items([('t', 4), ('h', 1), ('e', 7), (' ', 11), ('m', 1), ('a', 9), ('n', 2), ('l', 4), ('o', 4), ('v', 1), ('s', 5), ('r', 3), ('g', 2), (',', 1), ('b', 2), ('u', 2), ('c', 1), ('d', 1), ('p', 2)])

Entonces, con esto, sabemos que cuando una clave no existe, se llama al método __missing__. También se activa su atributo default_factory, que contiene una función que devuelve un valor.

Sin embargo, ¿podemos crear un defaultdict de un defaultdict? Sí, pero ¿cómo podemos hacerlo? Porque si le pasas un defaultdict a otro defaultdict, dará error.

from collections import defaultdict

d = defaultdict(defaultdict(int))
print(d)

Producción :

Traceback (most recent call last):
  File "c:\Users\USER\Desktop\JS\test.py", line 3, in <module>
    d = defaultdict(defaultdict(int))
TypeError: first argument must be callable or None

Se lanza un TypeError cuando ejecutamos el código, y esto sucedió debido a la línea d = defaultdict(defaultdict(int)), que dice que el primer argumento debe ser invocable o Ninguno.

Con esta información, podemos deducir que no pasamos un invocable (una función) o Ninguno (valor predeterminado que tiene default_factory), y eso es porque defaultdict(int) no es invocable. Es, sin embargo, un 'colecciones.defaultdict'.

Por lo tanto, necesitamos encontrar una manera de pasar un invocable, donde entra lambda.

lambda nos permite crear una función anónima a la que se puede llamar (un callable). Entonces, para el defaultdict de nivel superior, podemos pasar una función lambda que apunte al defaultdict(int), que se llamará cuando pasemos una clave inexistente.

La función lambda llama a la función factory dentro del defaultdict interno y devuelve su valor, que se establecerá como valor clave.

from collections import defaultdict

d = defaultdict(lambda: defaultdict(int))
print(d)

Producción :

defaultdict(<function <lambda> at 0x000001F6B9383E20>, {})

Para demostrar que funciona bien, podemos acceder al dictado predeterminado de nivel superior y al dictado predeterminado de nivel interno utilizando la notación cuadrada para ver sus valores predeterminados que deben pasarse a las funciones lambda e int, respectivamente .

print(d[0])
print(d[0][0])

Producción :

defaultdict(<class 'int'>, {})
0
Olorunfemi Akinlua avatar Olorunfemi Akinlua avatar

Olorunfemi is a lover of technology and computers. In addition, I write technology and coding content for developers and hobbyists. When not working, I learn to design, among other things.

LinkedIn

Artículo relacionado - Python Dictionary