2012-03-31 16 views
11

Raymond Hettinger showed una manera genial para combinar las clases de colección:subclases de OrderedDict y defaultdict

from collections import Counter, OrderedDict 
class OrderedCounter(Counter, OrderedDict): 
    pass 
# if pickle support is desired, see original post 

Quiero hacer algo similar para OrderedDict y defaultdict. Pero, por supuesto, defaultdict tiene una firma diferente __init__, por lo que requiere un trabajo adicional. ¿Cuál es la forma más limpia de resolver este problema? Yo uso Python 3.3.

He encontrado una buena solución aquí: https://stackoverflow.com/a/4127426/336527, pero estaba pensando que tal vez derivar de defaultdict podría hacer esto aún más simple?

+3

Mientras estamos en el tema, puede alguien explicarme cómo el ejemplo OrderedDict realmente obtiene funcionalidad OrderedDict sin ninguna 'super'-delegación explícita a esa clase? ¿Es debido a llamadas 'super' en algún lugar dentro de' Counter' que se redirigen a través de 'OrderedDict' en lugar de ir a' dict' directamente como lo harían normalmente? O solo que? –

+0

@KarlKnechtel Te refieres a 'OrderedCounter', pero es una buena pregunta. – agf

+0

@agf er, sí, exactamente. Stupid edit timeout ... :( –

Respuesta

7

Heredar de OrderedDict como en la respuesta se ha vinculado a es la forma más sencilla. Es más trabajo implementar una tienda ordenada que obtener valores predeterminados de una función de fábrica.

Todo lo que necesita implementar para defaultdict es un poco de lógica personalizada __init__ y la extremadamente simple __missing__.

Si en lugar de heredar de defaultdict, tiene que delegar o volver a implementar al menos __setitem__, __delitem__ y __iter__ para reproducir la operación en orden. Todavía tiene que hacer el trabajo de configuración en __init__, aunque es posible que pueda heredar o simplemente omitir algunos de los otros métodos según sus necesidades.

Eche un vistazo a the original recipe o any of the others linked to from another Stack Overflow question por lo que implicaría.

3

he encontrado una manera de subclase a ambos, pero no estoy seguro si hay errores:

class OrderedDefaultDict(defaultdict, OrderedDict): 
    def __init__(self, default, *args, **kwargs): 
     defaultdict.__init__(self, default) 
     OrderedDict.__init__(self, *args, **kwargs) 
+0

¿eso no dos diccionarios internos hacen? – leewz

+0

Oh, ya veo. yo sólo lea la publicación vinculada en la pregunta original. – leewz