2012-06-22 16 views
13

Estoy estudiando Python y actualmente estoy aprendiendo un poco más con los diccionarios.Divida un diccionario en las variables

Me preguntaba;

Si tengo un diccionario como: d = {'key_1': 'value_a', 'key_2': 'value_b'} y quiero separar/dividir este diccionario en variables donde cada variable es una clave del diccionario y el valor de cada variable es el valor de esa clave en el diccionario.

¿Cuál sería la mejor manera pitónica para lograr esto?

d = {'key_1': 'value_a', 'key_2': 'value_b'} 
#perform the command and get 
key_1 = 'value_a' 
key_2 = 'value_b' 

Intenté: key_1, key_2 = d pero no funcionó.

Básicamente estoy buscando la sabiduría de expertos para saber si hay una mejor manera de reducir 2 líneas de código en una.

Nota: Esta no es una creación de variable dinámica.

+1

Los diccionarios no tienen orden, por lo que es una tarea difícil crear una solución general, no es necesario hacer esto de todos modos. Si fue implementado, sería hacky. – jamylak

+4

No hay forma pitonica, porque la idea no es pitonica. En python, no desea crear variables dinámicamente. – georg

+2

No deberías hacer eso. La respuesta es 'key_1, key_2 = d.values ​​()'. pero 1) esto es propenso a excepciones; 2) no sabrá cuál es cuál, a menos que ordene 'd.values ​​()' antes de la asignación. Es muy poco probable que necesites todo esto. –

Respuesta

8

El problema es que los dicts no están ordenados, por lo que no puede usar el desembalaje simple de d.values(). Se podría, por supuesto primero ordenar el dict con llave, y luego descomprimir los valores:

ds = sorted(d.iteritems()) 
name0, name1, name2..., namen = [v[1] for v in ds] 

usted podría también, al menos dentro de un objeto, hacer algo como:

for k, v in dict.iteritems(): 
    setattr(self, k, v) 

Además, como he mencionado en el comentario anterior, si se puede obtener toda la lógica que necesita su diccionario descomprimido como variables a una función, se podría hacer:

def func(**kwargs): 
    # Do stuff with labeled args 

func(**d) 
+0

Muchas gracias por leer mi pregunta y responder. Creo que será mejor que siga la ruta estándar de separar el dict en variables yo mismo. Solo pensé que podría haber una solución de una línea sin iterar ni ordenar, pero supongo que no. así que haré key = dict ['key'] para cada tecla. Pero muchas gracias por esto. – Phil

+0

Si su caso de uso permite que su diccionario de origen sea un 'OrderedDict', y puede predecir el orden de inserción, puede omitir el orden y simplemente descomprimir' od.values ​​() 'directamente. –

+0

En este caso de uso, parece una exageración, pero gracias. Usted me pensó algo. valores cosa se ve muy útil. – Phil

0

no es recomendable para declarar las variables siempre dynami Cally, porque se vuelve muy difícil encontrar la fuente de un nombre de variable. Dicho esto, es posible hackear juntos una solución Dynamic variable name in python pero yo no lo recomendaría. Probablemente sea mejor usar un viejo diccionario simple.

+0

Hola, no estoy tratando de crear dinámicamente variables. Quiero reducir n cantidad de líneas (n es el conteo de teclas en el dict) a una sola línea. Pensé que sería posible con Python, pero ahora supongo que no. – Phil

1

De hecho, tengo un caso de uso, donde me tire todos los argumentos de un método __init__ en el mismo espacio de nombres en la construcción de objetos:

vars(self).update(somedict) 

La función vars le consigue un diccionario del “espacio de nombres” asociado con el objeto pasado. Sin embargo, esto no funcionará con los locales en una función, debido a los detalles de implementación de CPython. Por lo tanto, se supone que no funciona en todos los intérpretes.

Para el espacio de nombres global sustituiría vars(self) con globals(), pero esto es realmente una señal de que algo está mal con su lógica. Como se dijo, para las variables locales esto no funcionará de todos modos (será NameError incluso si asignó un valor al dict).

+0

¡Muchas gracias! – Phil

1

Usted puede hacer esto, si eres valiente:

for k, v in d.items(): 
    locals()[k] = v 

Pero ser valiente podría no ser suficiente - que también podría tener que ser imprudente etc.

Si quieres ser un héroe imprudente como @ecatmur, usted puede hacer esto:

locals().update(d) 

Pero ahora que la OP ha actualizado su pregunta y los comentarios contestadas, al parecer, esto no es lo que realmente quiere hacer. Solo para que conste: hay buenas razones para crear dinámicamente variables, incluso si todos aquí están de acuerdo en que no es pitónico. Muchos problemas de estilo de intérprete se pueden resolver directamente con la alteración dinámica de su alcance. Solo haz esto de forma controlada. Y ... uh, no implementar esta a un sitio de producción;)

+0

O incluso 'locals(). Update (d)'. – ecatmur

+0

@ecatmur, eres un héroe! –

+1

Por cierto, no lo hagas nunca - por http://docs.python.org/library/functions.html#locals * El contenido de este diccionario no debe modificarse; los cambios pueden no afectar los valores de las variables locales y gratuitas utilizadas por el intérprete. * – ecatmur

12

Una solución que no ha sido mencionado antes habría

dictget = lambda d, *k: [d[i] for i in k] 

y luego usarlo:

key_1, key_2 = dictget(d, 'key_1', 'key_2') 

cuya ventaja es que es bastante legible incluso con más variables que recuperar.

Incluso más fácil de leer, sin embargo, habría una función "real" como

def dictget(d, *k): 
    """Get the values corresponding to the given keys in the provided dict.""" 
    return [d[i] for i in k] 
    # or maybe 
    return (d[i] for i in k) # if we suppose that we have bigger sets of result 
    # or, equivalent to this 
    for i in k: 
     yield d[i] 

que además soporta comentando con una cadena de documentación y ha de preferirse.

+0

¡Excelente y elegante! – Phil

+0

@Phil No es tan real. Por lo tanto, acabo de agregar la solución 'def'. – glglgl

1

creo que esto debería resolver su problema

d = {'key_1': 'value_a', 'key_2': 'value_b'} 
for k,v in d.items(): 
    exec '%s=%s'%(k,v) 
+0

Esto funciona para valores que no son necesariamente cadenas: 'para k en my_dict.keys(): exec" {0} = my_dict [\ '{0} \'] ". Format (k)' –

1
var1, var2 = (lambda key1, key2: (key1, key2))(**d) 

Si desea dar a cualquiera que lea el código de un dolor de cabeza puede utilizar la función anónima para desempaquetar los valores de este tipo.

Cuestiones relacionadas