2011-05-22 15 views
14

Al utilizar claves de diccionario (dict) en Python, parece que hay algunos enfoques generales:¿Cuáles son las mejores prácticas de Python para las constantes de clave dict del diccionario?

  1. some_dict['key_name'] # string constants everywhere

  2. some_dict[KeyConstants.key_name] # where class KeyConstants: key_name: 'key_name'

  3. some_dict[KEY_NAME] # with from some_module import KEY_NAME # a module level constant

    1. 'nombre_tecla 'tiene la desventaja de que estás repitiendo consta en todo tu código. No es SECO. Peor aún, si alguna vez vas a publicar tu API (en el sentido más amplio), los consumidores de tu API repetirán estas constantes en todas partes, y si alguna vez quieres cambiar 'key_name' por 'better_key_name', será un cambio radical .

    2. Este es el lenguaje tipeado, enfoque DRY, con constantes consolidadas en un solo lugar. Sus únicas desventajas son que es feo, un poco menos legible y más detallado. Los principios Pythonic principalmente prohíben eso. Le permite cambiar fácilmente la constante que representa la clave, ya que todos codifican contra la variable KeyConstants.key_name. También funciona bien con IDEs para refactorización.

    3. Las constantes de nivel del módulo se recomiendan en la guía de estilo PEP 8. ALL_CAPS_ARE_LOUD y más difícil de escribir. Esto tiene algunas de las ventajas de ambas opciones 1 y 2.

¿Cuáles son algunas otras mejores prácticas para las constantes clave dict? ¿Cuál de los enfoques anteriores se prefiere y cuándo?

+2

¿Por qué tener tantas llaves constantes en primer lugar? ¿Por qué no usar variables de nivel de módulo o atributos de retención de objeto tipo registro? – delnan

+5

Los dictados son buenos si las claves son variables, de lo contrario puede ir con tuplas o atributos con nombre en una clase. Usar claves constantes debería ser una ocasión muy rara. –

+3

El problema de dict con claves es extremadamente común cuando se usa JSON o cuando se trata de una base de datos/tienda nosql sin un ORM (por ejemplo, pymongo sin MongoEngine). Si bien puedes ajustar las claves dict en clases con atributos, terminarás con un feo código de plomería para empaquetar/desempacar si los datos subyacentes eran dict para empezar. – velshin

Respuesta

3
  1. d [ 'nombre_tecla']
  2. d [Keys.key_name]
  3. d [KEY_NAME]

Realmente no vista # 3 como requerir importaciones a nivel de módulo; simplemente pueden estar en el nombre del módulo, p. ej. podría hacer algo como How to programmatically set a global (module) variable?

La ventaja de # 2 sobre # 1 es que los errores tipográficos y obsoletos arrojarán un error de atributo "¡esta clave no existe!" en lugar de un error de índice "no se pudo encontrar" - que es siempre mejor. # 2> # 1. Tampoco es más detallado, porque acaba de establecer K=Keys (o algo así) si está escribiendo mucho, por lo que tiene d[K.key_name], solo dos caracteres más(). Por ejemplo, dependiendo de cómo antes de que yo estoy sintiendo, me permite hacer cualquiera:

import subprocess as proc 
proc.Popen(..., stdout=proc.PIPE) 

o

import subprocess as proc 
PIPE = proc.PIPE 
proc.Popen(..., stdout=PIPE) 

o

from subprocess import * 
Popen(..., stdout=PIPE) 

Con respecto a # 3, ALL_CAPS_ARE_LOUD por una razón; se vuelve confuso distinguir entre d[someVariable] (que puede contener cualquier palabra clave) y d[magicKeyword] - mientras que d[MAGIC_KEYWORD] no es ambiguo que es una constante, y no una variable que puede estar conteniendo una constante, p. for someVariable in magicKeywords.# 3 básicamente es equivalente a a # 2, p. re.DOTALL (el re es equivalente a KeyConstants, sin tener que recordar el nombre de los contenedores KeyConstants porque es el módulo). Por lo tanto, el n. ° 3 es superior al n. ° 2 a menos que se encuentre en una situación extraña en la que tenga diferentes tipos de espacios de teclado.

DRY/OAOO es muy muy importante, pero en última instancia no es relevante para ninguno de estos, porque siempre necesita repetir un nombre de variable para referirse a él; lo mejor que puedes hacer es crear un alias.

También podría considerar # 4, que es dotar a su diccionario de atributos, p. d.key_name - esto solo es apropiado si se trata de algún objeto subscriptable.

Sin embargo, para citar un comentario de Jochen Ritzel: "Utilización de claves constantes debe haber una muy rara ocasión" (atributos de un objeto de uso, o como él sugiere tal vez una tupla llamada, aunque siempre los he encontrado para ser difícil de manejar)

+1

Gracias por la respuesta reflexiva. Tenga en cuenta que con cualquiera de los NAMED_CONSTANTS estamos DRYing el valor de la constante; esto se aplica aunque sean llaves. Cuando las claves se asignan a json o a una base de datos, se vuelve más claro por qué el nombre de la clave dict y NAMED_CONSTANT_KEY podrían variar de forma independiente. – velshin

1

Es una vieja pregunta, pero ¿has comprobado Bunch? Es un diccionario que admite el acceso de estilo de atributo, a la JavaScript.

>>> from bunch import bunchify 
>>> from bunch import unbunchify 
>>> import datetime as dt 

>>> my_dict = {'a': 'a', 'b': [{'c': 'c', 'n': 1}, {'c': 'k', 'n': 2}], 'dt': dt.datetime.utcnow()} 

>>> my_dict_obj = bunchify(my_dict) 
>>> my_dict_obj.b[0].c 
'c' 
>>> 'a' in my_dict_obj 
True 
>>> 'x' in my_dict_obj 
False 
>>> my_dict = unbunchify(my_dict_obj) 
Cuestiones relacionadas