print - Python: si teclea dict vs. try/except
try except python 3 print error (9)
Tengo una pregunta sobre modismos y legibilidad, y parece que hay un choque de filosofías de Python para este caso particular:
Quiero construir el diccionario A desde el diccionario B. Si una clave específica no existe en B, entonces no haga nada y continúe.
¿Qué camino es mejor?
try:
A["blah"] = B["blah"]
except KeyError:
pass
o
if "blah" in B:
A["blah"] = B["blah"]
"Haz y pide perdón" vs. "simplicidad y explicitud".
¿Cuál es mejor y por qué?
¿Por qué no justed hacer esto?
def try_except(x,col):
try:
return x[col]
except:
return None
list(map(lambda x: try_except(x,''blah''),A))
Cita directa de la wiki de rendimiento de Python:
Excepto por primera vez, cada vez que se ve una palabra, la prueba de la declaración if falla. Si está contando una gran cantidad de palabras, muchas probablemente se repitan varias veces. En una situación donde la inicialización de un valor solo va a ocurrir una vez y el aumento de ese valor ocurrirá muchas veces, es más barato usar una declaración try.
Entonces parece que ambas opciones son viables dependiendo de la situación. Para obtener más información, puede consultar este enlace: Try-except-performance
Creo que el segundo ejemplo es a lo que debes ir a menos que este código tenga sentido:
try:
A["foo"] = B["foo"]
A["bar"] = B["bar"]
A["baz"] = B["baz"]
except KeyError:
pass
Tenga en cuenta que el código abortará tan pronto como haya una clave que no esté en B
Si este código tiene sentido, entonces debe usar el método de excepción; de lo contrario, utilice el método de prueba. En mi opinión, porque es más corto y expresa claramente la intención, es mucho más fácil de leer que el método de excepción.
Por supuesto, las personas que le dicen que use la update
son correctas. Si está utilizando una versión de Python compatible con las comprensiones de los diccionarios, preferiría mucho este código:
updateset = {''foo'', ''bar'', ''baz''}
A.update({k: B[k] for k in updateset if k in B})
Creo que la regla general aquí es que A["blah"]
normalmente existe, si es así, intente, excepto que es bueno si no, entonces use if "blah" in b:
Creo que "probar" es barato en el tiempo, pero "excepto" es más caro.
La regla en otros idiomas es reservar excepciones para condiciones excepcionales, es decir, errores que no ocurren en el uso regular. No sé cómo se aplica esa regla a Python, ya que StopIteration no debería existir según esa regla.
Las excepciones no son condicionales.
La versión condicional es más clara. Eso es natural: este es un control de flujo directo, que es para lo que están diseñados los condicionales, no excepciones.
La versión de excepción se usa principalmente como optimización cuando se realizan estas búsquedas en un bucle: para algunos algoritmos, permite eliminar las pruebas de los bucles internos. No tiene ese beneficio aquí. Tiene la pequeña ventaja de que evita tener que decir "blah"
dos veces, pero si estás haciendo mucho de esto probablemente deberías tener una función de ayuda move_key
todos modos.
En general, recomiendo seguir con la versión condicional de forma predeterminada a menos que tenga una razón específica para no hacerlo. Los condicionales son la forma obvia de hacer esto, que suele ser una recomendación fuerte para preferir una solución sobre otra.
Personalmente, me inclino por el segundo método (pero usando has_key
):
if B.has_key("blah"):
A["blah"] = B["blah"]
De esta forma, cada operación de asignación es solo de dos líneas (en lugar de 4 con try / except), y cualquier excepción que se genere serán errores reales o cosas que haya omitido (en lugar de solo intentar acceder a claves que no están allí) .
Resulta que (ver los comentarios de su pregunta), has_key
está en desuso, así que supongo que está mejor escrito como
if "blah" in B:
A["blah"] = B["blah"]
Por lo que entiendo, quieres actualizar el dict A con clave, pares de valores del dict B
update
es una mejor opción.
A.update(B)
Ejemplo:
>>> A = {''a'':1, ''b'': 2, ''c'':3}
>>> B = {''d'': 2, ''b'':5, ''c'': 4}
>>> A.update(B)
>>> A
{''a'': 1, ''c'': 4, ''b'': 5, ''d'': 2}
>>>
También hay una tercera forma que evita tanto las excepciones como la doble búsqueda, que pueden ser importantes si la búsqueda es costosa:
value = B.get("blah", None)
if value is None:
A["blah"] = value
En caso de que espere que el diccionario contenga valores None
, puede usar algunas constantes esotéricas más como NotImplemented
, Ellipsis
o hacer una nueva:
MyConst = object()
def update_key(A, B, key):
value = B.get(key, MyConst)
if value is not MyConst:
A[key] = value
De todos modos, usar update()
es la opción más legible para mí:
a.update((k, b[k]) for k in ("foo", "bar", "blah") if k in b)