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)
        ...

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)
    ...

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).


@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,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.