185 votes

Pourquoi un dict.update () python ne renvoie-t-il pas l'objet?

J'essaie de faire:

 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
 

Mais si je me sentais vraiment encombrant dans la fonction et que j'aurais préféré le faire:

         return self.add_award({
            "name" : name,
            "description" : desc_string % count,
            "points" : points,
            "parent_award" : parent,
        }.update(award_dict), siteAlias, alias).award
 

Pourquoi la mise à jour ne renvoie-t-elle pas l'objet pour que vous puissiez l'enchaîner?

JQuery fait cela pour faire du chaînage. Pourquoi n'est-ce pas acceptable en python?

258voto

Alex Martelli Points 330805

Python est surtout la mise en œuvre d'une manière pragmatique, teinté de saveur de commande de requête de séparation: des mutateurs retour None (de façon pragmatique induite par les exceptions telles que l' pop;-) donc elle ne peut pas être confondu avec les accesseurs (et dans la même veine, la cession n'est pas une expression, l'énoncé de l'expression de la séparation est là, et ainsi de suite).

Cela ne signifie pas qu'il n'y a pas beaucoup de façons de fusionner les choses quand vous voulez, par exemple, dict(a, **award_dict) fait un nouveau dict un peu comme celui que vous semblez souhaiter .update retourné -- alors, pourquoi ne pas l'utiliser si vous vous sentez vraiment qu'il est important?

Edit: btw, pas besoin, dans votre cas particulier, de créer a le long de la voie, soit:

dict(name=name, description=desc % count, points=points, parent_award=parent,
     **award_dict)

crée un seul dict avec exactement la même sémantique que votre a.update(award_dict) (y compris, en cas de conflit, le fait que les entrées en award_dict remplacent celles que vous donnez explicitement; de l'autre sémantique, c'est à dire, explicite d'entrées de "gagner" de tels conflits, pass award_dict comme le seul de position arg, avant le mot-clé, et privé de l' ** -- dict(award_dict, name=name etc etc).

41voto

Martin v. Löwis Points 61768

API Python, par convention, la distinction entre les procédures et les fonctions. Les fonctions de calculer de nouvelles valeurs de leurs paramètres (y compris tout objet cible); les procédures de modifier des objets et ne rien retourner (c'est à dire Aucun retour). Si les procédures ont des effets secondaires, les fonctions ne font pas. mise à jour de la procédure, par conséquent, il ne retourne pas une valeur.

La motivation pour le faire de cette façon est que, sinon, vous risquez d'obtenir des effets secondaires indésirables. Envisager

bar = foo.reverse()

Si l'inverse (ce qui inverse la liste sur place) serait également renvoyer la liste, les utilisateurs peuvent penser que l'inverse renvoie une nouvelle liste qui sera affectée à la barre, et jamais d'avis que les foo obtient également modifié. En faisant inverser retour Aucun, ils ont immédiatement reconnaître que la barre n'est pas le résultat de l'inversion, et regarder de plus près ce que l'effet de l'inverse est.

17voto

 >>> dict_merge = lambda a,b: a.update(b) or a
>>> dict_merge({'a':1, 'b':3},{'c':5})
{'a': 1, 'c': 5, 'b': 3}
 

Notez que, en plus de renvoyer le dict fusionné, il modifie le premier paramètre sur place. Donc dict_merge (a, b) modifiera a.

Ou bien sûr, vous pouvez tout faire en ligne:

 >>> (lambda a,b: a.update(b) or a)({'a':1, 'b':3},{'c':5})
{'a': 1, 'c': 5, 'b': 3}
 

6voto

voyager Points 17283

Ce n'est pas que ce ne soit pas acceptable, mais plutôt que dicts n'ont pas été mis en œuvre de cette façon.

Si vous regardez l'ORM de Django, il utilise beaucoup le chaînage. Ce n'est pas découragé, vous pouvez même hériter de dict et ne substituer que update à la mise à jour et return self , si vous le souhaitez vraiment.

 class myDict(dict):
    def update(self, *args):
    	dict.update(self, *args)
    	return self
 

1voto

Matt Points 426
import itertools
dict_merge = lambda *args: dict(itertools.chain(*[d.iteritems() for d in args]))

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X