Diccionario o frases If, Jython

Estoy escribiendo un script en este momento que tomará cierta información de HTML usando dom4j.

Como Python / Jython no tiene una instrucción de cambio nativo, decidí usar un montón de instrucciones if que llaman al método apropiado, como a continuación:

if type == 'extractTitle': extractTitle(dom) if type == 'extractMetaTags': extractMetaTags(dom) 

Agregaré más dependiendo de la información que desee extraer del HTML y pensar en adoptar el enfoque de diccionario que encontré en otra parte de este sitio, ejemplo a continuación:

 { 'extractTitle': extractTitle, 'extractMetaTags': extractMetaTags }[type](dom) 

Sé que cada vez que ejecuto el script, se construirá el diccionario, pero al mismo tiempo, si tuviera que usar las sentencias if , el script tendría que revisarlas todas hasta que llegara a la correcta. ¿Qué es lo que realmente me pregunto, cuál se desempeña mejor o generalmente es una mejor práctica para usar?

Actualización: @Brian – Gracias por la gran respuesta. Tengo una pregunta, si alguno de los métodos de extracción requiere más de un objeto, por ejemplo,

     handle_extractTag(self, dom, anotherObject) # Do something 

    ¿Cómo haría los cambios apropiados en el método de manejo para implementar esto? Espero que sepas lo que quiero decir 🙂

    Aclamaciones

    Para evitar especificar la etiqueta y el controlador en el dict, puede utilizar una clase de controlador con métodos nombrados para que coincida con el tipo. P.ej

     class MyHandler(object): def handle_extractTitle(self, dom): # do something def handle_extractMetaTags(self, dom): # do something def handle(self, type, dom): func = getattr(self, 'handle_%s' % type, None) if func is None: raise Exception("No handler for type %r" % type) return func(dom) 

    Uso:

      handler = MyHandler() handler.handle('extractTitle', dom) 

    Actualizar:

    Cuando tenga múltiples argumentos, simplemente cambie la función de manejar para tomar esos argumentos y pasarlos a la función. Si desea hacerlo más genérico (para no tener que cambiar las funciones del controlador y el método de manejo cuando cambia la firma del argumento), puede usar la syntax * args y ** kwargs para pasar por todos los argumentos recibidos . El método de manejo entonces se convierte en:

     def handle(self, type, *args, **kwargs): func = getattr(self, 'handle_%s' % type, None) if func is None: raise Exception("No handler for type %r" % type) return func(*args, **kwargs) 

    Con tu código estás ejecutando tus funciones, todas son llamadas.

     manejadores = {
     'extractTitle': extractTitle, 
     'extractMetaTags': extractMetaTags
     }
    
     manejadores [tipo] (dom)
    

    Funcionaría como su código original.

    Depende de cuántas afirmaciones estamos hablando; si es un número muy pequeño, será más eficiente que usar un diccionario.

    Sin embargo, como siempre, le recomiendo encarecidamente que haga lo que haga que su código se vea más limpio hasta que la experiencia y los perfiles le indiquen que es necesario optimizar un bloque de código específico.

    Su uso del diccionario no es del todo correcto. En su implementación, todos los métodos serán llamados y todos los inútiles serán descartados. Lo que se suele hacer es algo más como:

     switch_dict = {'extractTitle': extractTitle, 'extractMetaTags': extractMetaTags} switch_dict[type](dom) 

    Y así es más fácil y más extensivo si tiene un número grande (o variable) de elementos.

    La cuestión de la eficiencia es apenas relevante. La búsqueda en el diccionario se realiza con una técnica de hashing simple, las sentencias if se deben evaluar de una en una. Los diccionarios suelen ser más rápidos.

    Le sugiero que tenga objetos polimórficos que realicen extracciones del DOM.

    No está claro cómo se establece el type , pero parece que podría ser una familia de objetos relacionados, no una simple cadena.

     class ExtractTitle( object ): def process( dom ): return something class ExtractMetaTags( object ): def process( dom ): return something 

    En lugar de establecer type = “extractTitle”, harías esto.

     type= ExtractTitle() # or ExtractMetaTags() or ExtractWhatever() type.process( dom ) 

    Entonces, no estarías construyendo este diccionario particular o statement if.