Polymorphism In Python

  • Haben Sie also eine Schnittstellenklasse namens iResource sowie mehrere Unterklassen, die jeweils die Funktion "Anfrage" implementieren. Da die Anforderungsroutinen Socket-E/A zu anderen Computern verwenden, sollten sie asynchron ausgeführt werden, damit die anderen Computer parallel arbeiten können. Wenn ich einen Thread mit iResource.request starte und eine Unterklasse als ersten Parameter übergebe, wird die Superklassenfunktion aufgerufen. Wenn ich es mit "type(a).request" und "a" als erstem Parameter beginne, bekomme ich "" für den Typwert (a). Irgendwelche Ideen, was das impliziert und wie man den wahren Typ der Methode bestimmt? Ist es möglich, eine abstrakte Methode in Python explizit zu deklarieren?


    Code
    def getSocialResults(self, query=''):
        #for a in self.types["social"]: print type(a)
        tasks = [type(a).request for a in self.types["social"]]
        argss = [(a, query, 0) for a in self.types["social"]]
    
        grabbers = executeChainResults(tasks, argss)
    
        return igrabber.cycleGrabber(grabbers)

    „executeChainResults“ akzeptiert eine Liste „Tasks“ von Callables und eine Liste „argss“ von Args-Tupeln und geht davon aus, dass jedes eine Liste zurückgibt. Es führt dann jeweils einen anderen Thread durch und verkettet die Ergebnislisten. Ich kann diesen Code bei Bedarf posten, aber ich hatte keine Probleme damit, also werde ich ihn vorerst ausschließen.

    Die Objekte "a" sind DEFINITIV nicht vom Typ iResource, da sie eine einzelne Funktion Object() { [native code] } haben, die nur eine Ausnahme auslöst, laut diesem Artikel. Das Ersetzen von „type(a).request“ durch „iResource.request“ führt jedoch die Basisklassenfunktion aus. Darüber hinaus funktioniert die direkte Verwendung von "self.types["social"][0].request" ordnungsgemäß, der vorhergehende Code gibt jedoch zurück: "type object 'instance' has no attribute'request'".

    Wenn Sie die auskommentierte Zeile wiederholt auskommentieren, wird <type 'instance'> ausgegeben.

    Jede Hilfe wäre willkommen

  • shamzi097 ”Schnittstellenklase” klingt als würde hier jemand versuchen Java in Python zu schreiben. Das sollte man nicht machen. Entweder hat meine Abstrakte Klasse die auch tatsächlich Teilfunktionalität implementiert, oder man hat einfach gar keine Klasse, sondern Dokumentation die das Protokoll beschreibt, was die Funktion oder Methode von solchen Werten erwartet.


    Die Verwendung von `type()` macht hier keinen Sinn. Das die richtige Methode auf dem richtigen Typ aufgerufen wird, passiert doch schon automatisch wenn man einfach die Methode auf dem Wert aufruft. Das muss man sich nicht noch mal nachprogrammieren.


    Python
        def get_social_results(self, query=""):
            social_types = self.types["social"]
            return igrabber.cycle_grabber(
                execute_chain_results(
                    [social_type.request for social_type in social_types],
                    [(query, 0)] * len(social_types),
                )
            )


    Die API von `execute_chain_results()` ist komisch, das man da zwei ”parallele” Listen übergeben muss. Besser wäre eine Sequenz (oder gar nur etwas iterierbares) über aufrufbare Objekte, die ihre Argumente bereits kennen. Diese Bindung kann man beispielsweise mit `functools.partial()` machen. Könnte dann so aussehen:

    Python
        def get_social_results(self, query=""):
            return igrabber.cycle_grabber(
                execute_chain_results(
                    partial(social_type.request, query, 0)
                    for social_type in self.types["social"]
                )
            )

    “Es ist schon über so viele Dinge Gras gewachsen, dass man bald keiner Wiese mehr trauen kann.”