2010-08-14 10 views
18

He intentado hacer una subclase dict heredando desde UserDict.DictMixin que admita claves que no son manejables. El rendimiento no es una preocupación. Desafortunadamente, Python implementa algunas de las funciones en DictMixin tratando de crear un objeto dict desde la subclase. Puedo implementarlos yo mismo, pero estoy atascado en __cmp__.¿Hay alguna descripción de cómo funciona __cmp__ para objetos dict en Python 2?

No puedo encontrar una descripción sucinta de la lógica utilizada por el __cmp__ incorporado para la clase dict.

Respuesta

26

Si se está preguntando cómo comparar diccionarios obras, es la siguiente:

  • Para comparar dicts A y B, primer comparar sus longitudes. Si son desiguales, devuelve cmp (len (A), len (B)).
  • A continuación, busque la clave adiff en A que es la clave más pequeña para la que adiff not in B or A[adiff] != B[adiff]. (Si no existe tal clave, los dicts son iguales.)
  • También encuentre el bdiff de clave más pequeño en B para el que bdiff not in A or A[bdiff] != B[bdiff].
  • If adiff! = Bdiff, luego devuelve cmp (adiff, bdiff). Else return cmp (A [adiff], B [bdiff]).

En pseudo-código:

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]) 

Esto se traduce de la aplicación 2.6.3 en dictobject.c.

+0

¡Gracias amablemente! – DannoHung

+1

¿Sabía que leyendo la fuente de 'dict_compare' (http://svn.python.org/projects/python/trunk/Objects/dictobject.c) o está documentado en alguna parte? – unutbu

+3

Leí la fuente. –

0

No es una descripción de __cmp__here, pero yo creo que lo importante a destacar es que __cmp__ sólo se utiliza si no se definen los métodos de comparación “rico”, como __lt__ y __eq__. Además, en Python3, __cmp__ se elimina del idioma. Así que quizás evite el total de __cmp__ y simplemente defina __lt__ y __eq__.

+0

Sí, estoy tratando de hacer que la interfaz coincida con 2,4 dict (requisito de trabajo). Probablemente haré un lleno en el puerto 3.x de este código más adelante. – DannoHung

2

Una alternativa es utilizar el Asignación ABC del paquete collections. Está disponible en 2.6 y superiores. Simplemente hereda de colecciones. Asignación e implementación de los métodos __getitem__, __contains__ y __iter__. Obtienes todo lo demás de forma gratuita.

Cuestiones relacionadas