Estoy tratando de hacer:
award_dict = {
"url" : "http://facebook.com",
"imageurl" : "http://farm4.static.flickr.com/3431/3939267074_feb9eb19b1_o.png",
"count" : 1,
}
def award(name, count, points, desc_string, my_size, parent) :
if my_size > count :
a = {
"name" : name,
"description" : desc_string % count,
"points" : points,
"parent_award" : parent,
}
a.update(award_dict)
return self.add_award(a, siteAlias, alias).award
Pero si me siento realmente engorroso en la función, y hubiera preferido hacerlo:
return self.add_award({
"name" : name,
"description" : desc_string % count,
"points" : points,
"parent_award" : parent,
}.update(award_dict), siteAlias, alias).award
¿Por qué la actualización no devuelve el objeto para que pueda encadenar?
JQuery hace esto para encadenar. ¿Por qué no es aceptable en Python?
python
dictionary
language-design
language-features
Paul Tarjan
fuente
fuente
newdict = dict(dict001, **dict002)
Respuestas:
Python está implementando principalmente un sabor pragmáticamente teñido de separación de consulta de comando : los mutadores regresan
None
(con excepciones inducidas pragmáticamente comopop
;-) para que no puedan confundirse con los accesores (y en la misma línea, la asignación no es una expresión, la declaración -expresión de separación está ahí, y así sucesivamente).Eso no significa que no haya muchas maneras de fusionar las cosas cuando realmente quiere, por ejemplo, crea
dict(a, **award_dict)
un nuevo dictado muy parecido al que parece que desea.update
devolver, así que ¿por qué no usar ESO si realmente cree que es importante? ?Editar : por cierto, no es necesario, en su caso específico, crear
a
en el camino, ya sea:crea un solo dict con exactamente la misma semántica que la suya
a.update(award_dict)
(incluido, en caso de conflictos, el hecho de que las entradasaward_dict
anulan las que está dando explícitamente; para obtener la otra semántica, es decir, tener entradas explícitas que "ganen" tales conflictos, pasaraward_dict
como el único argumento posicional , antes las palabras clave, y sin el**
formulario (dict(award_dict, name=name
etc., etc.).fuente
a
completo, por cierto,TypeError
dict(old_dict, old_key=new_value)
no arrojará múltiples valores para la palabra clave y devolverá un nuevo dict.La API de Python, por convención, distingue entre procedimientos y funciones. Las funciones calculan nuevos valores a partir de sus parámetros (incluido cualquier objeto de destino); Los procedimientos modifican objetos y no devuelven nada (es decir, no devuelven ninguno). Entonces los procedimientos tienen efectos secundarios, las funciones no. La actualización es un procedimiento, por lo tanto, no devuelve un valor.
La motivación para hacerlo de esa manera es que de lo contrario, puede obtener efectos secundarios indeseables. Considerar
Si reverse (que invierte la lista en el lugar) también devolvería la lista, los usuarios pueden pensar que reverse devuelve una nueva lista que se asigna a la barra, y nunca notan que foo también se modifica. Al realizar el retorno inverso Ninguno, reconocen de inmediato que la barra no es el resultado de la inversión, y mirarán más de cerca cuál es el efecto de la inversión.
fuente
reverse(foo)
siente raro.bar=foo[:]
), luego revierta la copia.bar = foo.reverse()
, podrías pensar quefoo
no está modificado. Para evitar confusiones, tienes ambosfoo.reverse()
ybar = reversed(foo)
.Esto es fácil como:
fuente
Tenga en cuenta que además de devolver el dict combinado, modifica el primer parámetro en el lugar. Entonces dict_merge (a, b) modificará a.
O, por supuesto, puedes hacerlo todo en línea:
fuente
lambda
no debe usarse así, en su lugar use la función convencional en sudef
lugara.update(b) or a
no hay suficiente reputación para comentarios en la respuesta superior
@beardc esto no parece ser cosa de CPython. PyPy me da "TypeError: las palabras clave deben ser cadenas"
La solución
**kwargs
solo funciona porque el diccionario que se fusionará solo tiene claves de tipo cadena .es decir
vs
fuente
No es que no sea aceptable, sino que
dicts
no se implementaron de esa manera.Si nos fijamos en el ORM de Django, hace un amplio uso del encadenamiento. No se desaconseja, incluso podría heredar
dict
y solo anularupdate
para actualizar yreturn self
, si realmente lo desea.fuente
tan cerca de su solución propuesta como pude conseguir
fuente
Para aquellos que llegan tarde a la fiesta, había preparado un poco de tiempo (Py 3.7), demostrando que
.update()
métodos basados se ven un poco (~ 5%) más rápido cuando se conservan las entradas y notablemente (~ 30%) más rápido cuando solo se actualiza en el lugar .Como de costumbre, todos los puntos de referencia deben tomarse con un grano de sal.
Los tiempos para las operaciones en el lugar son un poco más complicados, por lo que debería modificarse junto con una operación de copia adicional (el primer tiempo es solo para referencia):
fuente
fuente
Solo he estado probando esto en Python 3.4 (por lo que no pude usar la
{**dict_1, **dict_2}
sintaxis elegante ).Quería poder tener claves sin cadenas en los diccionarios, así como proporcionar una cantidad arbitraria de diccionarios.
Además, quería hacer un nuevo diccionario, así que opté por no usarlo
collections.ChainMap
(como la razón por la que no quería usarlodict.update
inicialmente).Esto es lo que terminé escribiendo:
fuente