2010-08-14 21 views
18

J'ai essayé de faire une sous-classe dict héritant de UserDict.DictMixin qui prend en charge les clés non-gélifiables. La performance n'est pas une préoccupation. Malheureusement, Python implémente certaines des fonctions de DictMixin en essayant de créer un objet dict à partir de la sous-classe. Je peux les implémenter moi-même, mais je suis coincé sur __cmp__.Existe-t-il une description du fonctionnement de __cmp__ pour les objets dict dans Python 2?

Je ne trouve pas de description succincte de la logique utilisée par le __cmp__ intégré pour la classe dict.

Répondre

26

Si vous demandez comment comparer des œuvres de dictionnaires, il est ceci:

  • Pour comparer dicts A et B, d'abord comparer leurs longueurs. Si elles sont inégales, retournez cmp (len (A), len (B)). Ensuite, trouvez la clé adiff dans A qui est la plus petite clé pour laquelle adiff not in B or A[adiff] != B[adiff]. (S'il n'y a pas de telle clé, les dicts sont égaux.)
  • Recherchez également la plus petite clé bdiff dans B pour laquelle bdiff not in A or A[bdiff] != B[bdiff].
  • Si adiff! = Bdiff, alors retournez cmp (adiff, bdiff). Sinon, retournez cmp (A [adiff], B [bdiff]).

En pseudo-code:

def smallest_diff_key(A, B): 
    """return the smallest key adiff in A such that adiff not in B or A[adiff] != B[bdiff]""" 
    diff_keys = [k for k in A if k not in B or A[k] != B[k]] 
    return min(diff_keys) 

def dict_cmp(A, B): 
    if len(A) != len(B): 
     return cmp(len(A), len(B)) 
    try: 
     adiff = smallest_diff_key(A, B) 
    except ValueError: 
     # No difference. 
     return 0 
    bdiff = smallest_diff_key(B, A) 
    if adiff != bdiff: 
     return cmp(adiff, bdiff) 
    return cmp(A[adiff], b[bdiff]) 

Cela se traduit par la mise en œuvre de 2.6.3 en dictobject.c.

+0

Merci beaucoup! – DannoHung

+1

Le saviez-vous en lisant la source de 'dict_compare' (http://svn.python.org/projects/python/trunk/Objects/dictobject.c) ou est-il documenté quelque part? – unutbu

+3

J'ai lu la source. –

0

Il y a une description de __cmp__here, mais je pense que la chose importante à noter est que __cmp__ est utilisé que si les méthodes « comparaison riches », comme __lt__ et __eq__ ne sont pas définis. De plus, dans Python3, __cmp__ est supprimé du langage. Donc peut-être éviter __cmp__ tout à fait et juste définir __lt__ et __eq__.

+0

Ouais, j'essaie juste de faire correspondre l'interface 2.4 dict (travail requis). Je ferai probablement un port complet sur le port 3.x de ce code plus tard. – DannoHung

2

Une alternative consiste à utiliser le mappage ABC du package collections. Il est disponible en 2.6 et plus. Vous venez d'hériter de collections.Mapping et implémenter les méthodes __getitem__, __contains__ et __iter__. Vous obtenez tout le reste gratuitement.