Frage

Ich bin ein Skript zur Zeit zu schreiben, die bestimmte Informationen von HTML verwenden dom4j greifen wird.

Da Python / Jython haben keinen nativen Schalter Aussage, die ich eine ganze Reihe von zu verwenden, entschieden, ob Aussagen, die die entsprechende Methode aufrufen, wie unter:

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

Ich werde mehr werden, indem je nachdem, welche Informationen ich aus dem HTML extrahieren möchte und dachte über den Wörterbuch Ansatz, die ich an anderer Stelle auf dieser Website, zB unter:

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

Ich weiß, dass jedes Mal, wenn ich das Skript ausführen das Wörterbuch gebaut werden, aber zur gleichen Zeit, wenn ich die verwenden war, wenn Aussagen das Skript würde durch alle von ihnen hat zu prüfen, bis sie trifft die richtigen. Was ich wirklich fragen, was man besser abschneidet oder ist in der Regel eine bessere Praxis zu benutzen?

Update: @ Brian - Danke für die tolle Antwort. Ich habe eine Frage, wenn eine der Extrakt Verfahren mehr als ein Objekt erfordern, z.

handle_extractTag(self, dom, anotherObject)
# Do something

Wie würden Sie die entsprechenden Änderungen an der behandeln Methode implementiert das? Hoffe, dass Sie wissen, was ich meine:)

Prost

War es hilfreich?

Lösung

Um zu vermeiden, den Tag-und-Handler in der dict Angabe Sie könnten nur einen Handler-Klasse mit Methoden genannt, die Art zu entsprechen. Eg

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)

Verbrauch:

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

Update:

Wenn Sie mehrere Argumente haben, nur der Griff Funktion ändern diese Argumente zu nehmen und sie an die Funktion durch. Wenn Sie es mehr Generika machen wollen (so müssen Sie nicht sowohl die Handler-Funktionen und den Griff Methode ändern, wenn Sie das Argument Signatur ändern), können Sie die * args verwenden und ** kwargs Syntax durch alle Argumente empfangen passieren . Der Griff Methode wird dann:

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)

Andere Tipps

Mit Ihrem Code Sie laufen Ihre Funktionen alle aufgerufen.

handlers = {
'extractTitle': extractTitle, 
'extractMetaTags': extractMetaTags
}

handlers[type](dom)

Möchten Sie Ihre ursprüngliche if Code arbeiten.

Es hängt davon ab, wie viele, wenn Aussagen über die wir reden; wenn es sich um eine sehr kleine Zahl ist, dann wird es effizienter sein als ein Wörterbuch verwenden.

Aber wie immer, Ich rate Ihnen dringend, zu tun, was Ihr Code sieht Reiniger macht, bis Erfahrung und Profilieren Sie sagen, dass ein bestimmter Codeblock optimiert werden muss.

Ihre Nutzung des Wörterbuchs ist nicht ganz richtig. In Ihrer Implementierung werden alle Methoden aufgerufen und alle nutzlos einer verworfen. Was ist in der Regel ist so etwas wie getan:

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

Und auf diese Weise ist facter und mehr erweiterbar, wenn Sie eine große (oder Variable) Anzahl von Elementen haben.

Die Effizienz Frage ist kaum relevant. Die Wörterbuchsuche wird mit einem einfachen Hashing-Technik durchgeführt, die if-Anweisungen haben einer nach dem anderen zu bewerten. Wörterbücher sind in der Regel schneller sein.

Ich schlage vor, dass Sie tatsächlich polymorphe Objekte, die Extraktionen aus dem DOM tun.

Es ist nicht klar, wie type gesetzt wird, aber es sieht aus wie sicher es sich um eine Familie verwandter Objekte sein könnte, nicht eine einfache Zeichenfolge.

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

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

Statt Typ Einstellung = "extractTitle", würden Sie dies tun.

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

Dann würden Sie nicht diese besondere Wörterbuch bauen oder if-Anweisung.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top