Funkcja wywołania Pythona w klasie

242

Mam ten kod, który oblicza odległość między dwiema współrzędnymi. Obie funkcje należą do tej samej klasy.

Jak jednak wywołać funkcję distToPointw funkcji 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
źródło
41
try: self.distToPoint (p)
momeara
Co jeśli isNear i distToPoint przyjmują różne argumenty. W jaki sposób możemy wywołać distToPoint, który znajduje się w klasie? Każdy może mi to wytłumaczyć.
Raghavendra Gupta

Odpowiedzi:

394

Ponieważ są to funkcje składowe, nazywają ją jako funkcję członka na przykład self.

def isNear(self, p):
    self.distToPoint(p)
    ...
Jeff Mercado
źródło
2
Ale bądź ostrożny, self.foo () użyje kolejności rozwiązywania metod, która mogłaby rozwiązać funkcję w innej klasie.
Francis Davey,
Co się stanie, jeśli nie użyjemy siebie? i bezpośrednio wywołać distToPoint (p)?
Marlon Abeykoon,
3
@Marlon Abeykoon zabraknie argumentu „ja”
Pitipaty
1
Co jeśli isNear i distToPoint przyjmują różne argumenty. W jaki sposób możemy wywołać distToPoint, który znajduje się w klasie? Każdy może mi to wytłumaczyć.
Raghavendra Gupta
46

To nie działa, ponieważ distToPointjest wewnątrz swojej klasie, więc trzeba poprzedzić go z nazwy klasy, jeśli chcesz odnieść się do niego tak: classname.distToPoint(self, p). Nie powinieneś tego jednak robić. Lepszym sposobem na to, aby odnieść się do sposobu bezpośrednio na przykład klasy (który jest pierwszym argumentem metody klasy), tak jak poniżej: self.distToPoint(p).

Aleksi Torhamo
źródło
@Aleski. Jeśli jest to metoda ogólna (wspólna dla wszystkich instancji i bez zmiennych specyficznych dla instancji, do których odwołuje się metoda), czy możesz wyjaśnić, dlaczego nie należy używać nazwy klasy.distToPoint (self, p)?
Yugmorf,
2
@Yugmorf: Jest tylko jedna sytuacja, w której należy użyć classname.distToPoint(self, p): podczas definiowania podklasy, która zastępuje distToPoint, ale musi wywołać oryginał. Jeśli self.distToPoint(p)w takim przypadku spróbujesz zadzwonić normalnie, skończysz na wywołaniu metody, którą właśnie definiujesz, i uzyskasz nieskończoną rekurencję. Jeśli nie znajduje się w klasie, istnieje również tylko jedna sytuacja, w której powinieneś użyć classname.distToPoint(obj, p)zamiast obj.distToPoint(p): jeśli obj może być instancją podklasy, ale musisz wywołać pierwotnie distToPointzdefiniowaną (ciąg dalszy)
Aleksi Torhamo,
1
w classnamezamiast zastąpionej wersji podklasy - należy jednak pamiętać, że jest to bardzo hacky i nie powinny być wykonywane w ogóle bez bardzo dobrego powodu. Zauważ, że łamiesz polimorfizm podtypu, gdy wywołujesz metodę bezpośrednio przez klasę (w obu powyższych przykładach chcesz to zrobić). W skrócie: powinieneś wywoływać metodę jawnie poprzez klasę tylko wtedy, gdy musisz ominąć polimorfizm podtypu z jakiegoś [dobrego] powodu. Jeśli metoda nie została zastąpiona, dwa sposoby są równe, ale self.distToPoint(p)są krótsze i bardziej czytelne, (ciąg dalszy)
Aleksi Torhamo,
więc zdecydowanie powinieneś go nadal używać. Przejdźmy teraz do szczegółów pytania: jeśli twoja metoda nie używa żadnych zmiennych instancji, może zamiast tego powinna to być metoda klasowa? Tworzysz je dodając @classmethodprzed metodą, a potem nie otrzymasz już instancji ( self) jako pierwszego argumentu - zamiast tego dostajesz klasę, więc powinieneś nazwać pierwszy argument np. clszamiast. Następnie możesz wywołać metodę klasową obj.distToPoint(p)lub lub classname.distToPoint(p)(zauważ brak obj). Prawdopodobnie powinieneś nadal używać (ciąg dalszy)
Aleksi Torhamo,
obj.distToPoint(p), jeśli jednak masz odpowiednią instancję na rękach, chyba że - znowu - masz jakiś [dobry] powód, aby ominąć polimorfizm podtypu, ponieważ metoda klasowa mogłaby zostać w ogóle zastąpiona w podklasie. Oczywiście, jeśli nie masz odpowiedniego dostępnej instancji, powinieneś za wszelką cenę wywołać metodę klasy bezpośrednio przez klasę.
Aleksi Torhamo,