Python-Aufruffunktion innerhalb der Klasse

242

Ich habe diesen Code, der den Abstand zwischen zwei Koordinaten berechnet. Die beiden Funktionen gehören beide zur selben Klasse.

Wie rufe ich die Funktion distToPointin der Funktion auf isNear?

class Coordinates:
    def distToPoint(self, p):
        """
        Use pythagoras to find distance
        (a^2 = b^2 + c^2)
        """
        ...

    def isNear(self, p):
        distToPoint(self, p)
        ...
Steven
quelle
41
versuchen Sie: self.distToPoint (p)
momeara
Was ist, wenn isNear und distToPoint unterschiedliche Argumente verwenden? Wie können wir dann distToPoint aufrufen, das sich innerhalb der Klasse befindet? Das kann mir bitte jeder erklären.
Raghavendra Gupta

Antworten:

394

Da es sich um Elementfunktionen handelt, rufen Sie es als Elementfunktion für die Instanz auf self.

def isNear(self, p):
    self.distToPoint(p)
    ...
Jeff Mercado
quelle
2
Aber seien Sie vorsichtig. Self.foo () verwendet die Reihenfolge der Methodenauflösung, die möglicherweise in eine Funktion in einer anderen Klasse aufgelöst wird.
Francis Davey
Was passiert, wenn wir uns nicht selbst benutzen? und distToPoint (p) direkt aufrufen?
Marlon Abeykoon
3
@Marlon Abeykoon das Argument "Selbst" wird fehlen
Pitipaty
1
Was ist, wenn isNear und distToPoint unterschiedliche Argumente verwenden? Wie können wir dann distToPoint aufrufen, das sich innerhalb der Klasse befindet? Das kann mir bitte jeder erklären.
Raghavendra Gupta
46

Das funktioniert nicht, weil distToPointes sich in Ihrer Klasse befindet. Sie müssen ihm also den Klassennamen voranstellen, wenn Sie darauf verweisen möchten, wie folgt : classname.distToPoint(self, p). Du solltest es aber nicht so machen. Eine bessere Möglichkeit besteht darin, direkt über die Klasseninstanz (das erste Argument einer Klassenmethode) auf die Methode zu verweisen self.distToPoint(p).

Aleksi Torhamo
quelle
@ Aleski. Wenn es sich um eine generische Methode handelt (die allen Instanzen gemeinsam ist und keine instanzspezifischen Variablen enthält, auf die in der Methode verwiesen wird), können Sie bitte erklären, warum classname.distToPoint (self, p) nicht verwendet werden sollte.
Yugmorf
2
@Yugmorf: Es gibt nur eine Situation, die man verwenden sollte classname.distToPoint(self, p): Wenn Sie eine Unterklasse definieren, die überschreibt distToPoint, aber das Original aufrufen muss. Wenn Sie self.distToPoint(p)in diesem Fall versuchen würden, wie gewohnt aufzurufen , würden Sie am Ende die Methode aufrufen, die Sie gerade definieren, und in eine unendliche Rekursion geraten. Wenn Sie sich nicht in einer Klasse befinden, gibt es auch nur eine Situation, in der Sie classname.distToPoint(obj, p)stattdessen verwenden würden obj.distToPoint(p): Wenn obj eine Instanz der Unterklasse sein könnte, Sie aber das ursprünglich distToPointdefinierte (Fortsetzung)
aufrufen müssen
1
in classnameanstelle der überschriebenen Version in der Unterklasse - aber beachten Sie, dass diese sehr hacky und nicht ohne im Allgemeinen getan werden soll , sehr guten Grund. Beachten Sie, dass Sie den Subtyp-Polymorphismus unterbrechen, wenn Sie eine Methode explizit über eine Klasse aufrufen (in beiden obigen Beispielen möchten Sie dies speziell tun). Kurz gesagt: Sie sollten eine Methode nur dann explizit über eine Klasse aufrufen, wenn Sie aus irgendeinem [guten] Grund den Subtyp-Polymorphismus umgehen müssen . Wenn die Methode nicht überschrieben wurde, sind die beiden Möglichkeiten gleich, aber self.distToPoint(p)kürzer und besser lesbar (Fortsetzung)
Aleksi Torhamo
also solltest du es auf jeden fall noch benutzen. Kommen wir nun zu den Einzelheiten Ihrer Frage: Wenn Ihre Methode keine Instanzvariablen verwendet, sollte es sich stattdessen möglicherweise um eine Klassenmethode handeln. Sie erstellen diese, indem Sie sie @classmethodvor der Methode hinzufügen. Danach erhalten Sie keine Instanz ( self) mehr als erstes Argument. Stattdessen erhalten Sie die Klasse. Sie sollten also das erste Argument benennen, z. clsstattdessen. Danach können Sie die Klassenmethode entweder wie obj.distToPoint(p)oder aufrufen classname.distToPoint(p)(beachten Sie das Fehlen von obj). Sie sollten immer noch wahrscheinlich verwenden (Fortsetzung)
Aleksi Torhamo
obj.distToPoint(p)Wenn Sie jedoch nur eine relevante Instanz in Ihren Händen haben, es sei denn, Sie haben erneut einen [guten] Grund, den Subtyp-Polymorphismus zu umgehen, da die Klassenmethode im Allgemeinen auch in einer Unterklasse überschrieben werden könnte. Wenn Sie keine relevante Instanz zur Verfügung haben, sollten Sie eine Klassenmethode auf jeden Fall direkt über eine Klasse aufrufen .
Aleksi Torhamo