Eu estou tentando fazer:
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
Mas se me sentisse realmente complicado na função, e eu preferiria:
return self.add_award({
"name" : name,
"description" : desc_string % count,
"points" : points,
"parent_award" : parent,
}.update(award_dict), siteAlias, alias).award
Por que a atualização não retorna o objeto para que você possa encadear?
O JQuery faz isso para encadear. Por que não é aceitável em python?
python
dictionary
language-design
language-features
Paul Tarjan
fonte
fonte
newdict = dict(dict001, **dict002)
Respostas:
O Python está implementando principalmente um sabor pragmaticamente tingido de separação de consulta de comando : os mutadores retornam
None
(com exceções induzidas pragmaticamente comopop
;-), para que não possam ser confundidas com os acessadores (e na mesma linha, atribuição não é uma expressão, a instrução separação de expressão existe e assim por diante).Isso não significa que não há muitas maneiras de mesclar as coisas quando você realmente deseja, por exemplo, cria
dict(a, **award_dict)
um novo ditado muito parecido com o que você parece desejar.update
retornar - então, por que não usá-lo se realmente acha importante ?Edit : btw, não é necessário, no seu caso específico, criar
a
ao longo do caminho:cria um único ditado com exatamente a mesma semântica que a sua
a.update(award_dict)
(incluindo, no caso de conflitos, o fato de que as entradasaward_dict
substituem as que você está dando explicitamente; para obter a outra semântica, ou seja, para ter entradas explícitas "vencendo" esses conflitos, passaraward_dict
como o único argumento posicional , antes das palavras-chave e sem o**
formulário -dict(award_dict, name=name
etc etc).fonte
a
, btw,TypeError
dict(old_dict, old_key=new_value)
não lançará vários valores para a palavra-chave e retornará um novo ditado.A API do Python, por convenção, distingue entre procedimentos e funções. As funções calculam novos valores a partir de seus parâmetros (incluindo qualquer objeto de destino); Os procedimentos modificam objetos e não retornam nada (ou seja, eles retornam Nenhum). Portanto, procedimentos têm efeitos colaterais, funções não. update é um procedimento, portanto, ele não retorna um valor.
A motivação para fazer dessa maneira é que, caso contrário, você poderá obter efeitos colaterais indesejáveis. Considerar
Se reverse (que inverte a lista no local) também devolve a lista, os usuários podem pensar que reverse retorna uma nova lista que é atribuída à barra e nunca notam que foo também é modificado. Fazendo retorno reverso Nenhum, eles imediatamente reconhecem que a barra não é o resultado da reversão e parecerão mais próximos do efeito do reverso.
fonte
reverse(foo)
parece estranho.bar=foo[:]
) e depois reverter a cópia.bar = foo.reverse()
, você poderia pensar quefoo
não é modificado. Para evitar confusão, você tem ambosfoo.reverse()
ebar = reversed(foo)
.Isso é fácil como:
fonte
Observe que, além de retornar o ditado mesclado, ele modifica o primeiro parâmetro no local. Então dict_merge (a, b) modificará a.
Ou, é claro, você pode fazer tudo em linha:
fonte
lambda
não deve ser utilizado como que, em vez disso usar função convencionaldef
em veza.update(b) or a
reputação insuficiente para o comentário deixado na resposta superior
@ Beardc isso não parece ser coisa de CPython. PyPy me fornece "TypeError: palavras-chave devem ser cadeias de caracteres"
A solução
**kwargs
funciona apenas porque o dicionário a ser mesclado possui apenas chaves do tipo string .ie
vs
fonte
Não é que não seja aceitável, mas que
dicts
não foi implementado dessa maneira.Se você observar o ORM do Django, ele faz uso extensivo de encadeamento. Não é desencorajado, você pode até herdar
dict
e substituir apenasupdate
para atualizar ereturn self
, se você realmente quiser.fonte
o mais próximo possível da sua solução proposta
fonte
Para aqueles que chegaram atrasados à festa, eu tinha marcado um tempo (Py 3.7), mostrando que
.update()
métodos baseados parecem um pouco (~ 5%) mais rápidos quando as entradas são preservadas e visivelmente (~ 30%) mais rápidos quando apenas atualizamos no local .Como sempre, todas as referências devem ser tomadas com um grão de sal.
Os tempos para as operações no local são um pouco mais complicados, portanto, ele precisa ser modificado ao longo de uma operação de cópia extra (o primeiro tempo é apenas para referência):
fonte
fonte
Apenas tentei isso no Python 3.4 (por isso não foi capaz de usar a
{**dict_1, **dict_2}
sintaxe sofisticada ).Eu queria poder ter chaves não-string nos dicionários, além de fornecer uma quantidade arbitrária de dicionários.
Além disso, eu queria criar um novo dicionário, por isso optei por não usar
collections.ChainMap
(meio que o motivo de não querer usardict.update
inicialmente.Aqui está o que eu acabei escrevendo:
fonte