Función de llamada de Python dentro de la clase

242

Tengo este código que calcula la distancia entre dos coordenadas. Las dos funciones están dentro de la misma clase.

Sin embargo, ¿cómo llamo a la función distToPointen la función 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
fuente
41
try: self.distToPoint (p)
momeara
¿Qué pasa si isNear y distToPoint están tomando diferentes argumentos? Entonces, ¿cómo podemos llamar a distToPoint que está dentro de la clase? Cualquiera puede explicar eso por mí, por favor.
Raghavendra Gupta

Respuestas:

394

Puesto que éstas son funciones miembro, llamar como una función miembro en la instancia, self.

def isNear(self, p):
    self.distToPoint(p)
    ...
Jeff Mercado
fuente
2
Pero tenga cuidado self.foo () usará el orden de resolución del método que podría resolver una función en una clase diferente.
Francis Davey
¿Qué pasa si no usamos uno mismo? y llame directamente a distToPoint (p)?
Marlon Abeykoon
3
@Marlon Abeykoon, el argumento del "yo" estará ausente
Pitipaty
1
¿Qué pasa si isNear y distToPoint están tomando diferentes argumentos? Entonces, ¿cómo podemos llamar a distToPoint que está dentro de la clase? Cualquiera puede explicar eso por mí, por favor.
Raghavendra Gupta
46

Que no funciona porque distToPointestá dentro de su clase, por lo que necesita el prefijo con el nombre de clase, si se desea hacer referencia a ella, como esto: classname.distToPoint(self, p). Sin embargo, no deberías hacerlo así. Una mejor manera de hacerlo es hacer referencia al método directamente a través de la instancia de clase (que es el primer argumento de un método de clase), así: self.distToPoint(p).

Aleksi Torhamo
fuente
@Aleski. Si es un método genérico (común a todas las instancias y sin ninguna variable específica de instancia a la que se haga referencia en el método), ¿podría explicar por qué uno no debería usar classname.distToPoint (self, p)?
Yugmorf
2
@Yugmorf: Solo hay una situación en la que uno debería usar classname.distToPoint(self, p): cuando está definiendo una subclase que anula distToPoint, pero necesita llamar al original. Si trataste de llamar self.distToPoint(p)como normal en ese caso, terminarías llamando al método que estás definiendo y entrarías en una recursión infinita. Si no está dentro de una clase, solo hay una situación en la que usaría en classname.distToPoint(obj, p)lugar de obj.distToPoint(p): si obj podría ser una instancia de la subclase, pero debe llamar al original distToPointdefinido (continuación)
Aleksi Torhamo
1
en classnamelugar de la versión anulada en la subclase, pero tenga en cuenta que esto es muy hacky y no debe hacerse en general sin una muy buena razón. Tenga en cuenta que rompe el polimorfismo de subtipo cuando llama a un método explícitamente a través de una clase (en los dos ejemplos anteriores, específicamente desea hacer eso). En resumen: solo debe llamar a un método explícitamente a través de una clase cuando necesita sortear el polimorfismo de subtipo por alguna [buena] razón. Si el método no se ha anulado, las dos formas son iguales, pero self.distToPoint(p)es más corto y más legible, (continuación)
Aleksi Torhamo
así que definitivamente deberías usarlo. Ahora, llegando a los detalles de su pregunta: si su método no usa ninguna variable de instancia, ¿tal vez debería ser un método de clase? Los haces agregando @classmethodantes del método, y después de eso ya no obtendrás una instancia ( self) como primer argumento; en cambio, obtienes la clase, por lo que debes nombrar el primer argumento, por ejemplo. clsen lugar. Después de eso, puede llamar al método de clase como like obj.distToPoint(p)o classname.distToPoint(p)(tenga en cuenta la falta de obj). Probablemente aún deberías usar (continuación)
Aleksi Torhamo
obj.distToPoint(p)Sin embargo, si solo tiene una instancia relevante en sus manos, a menos que, nuevamente, tenga alguna [buena] razón para eludir el polimorfismo de subtipo, ya que el método de clase también podría haberse anulado en una subclase, en general. Por supuesto, si no tiene una instancia relevante disponible, debería llamar a un método de clase directamente a través de una clase.
Aleksi Torhamo