Função de chamada Python dentro da classe

242

Eu tenho esse código que calcula a distância entre duas coordenadas. As duas funções estão dentro da mesma classe.

No entanto, como chamo a função distToPointna função 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
fonte
41
Tente: self.distToPoint (p)
momeara
E se isNear e distToPoint estiverem usando argumentos diferentes. Então, como podemos chamar distToPoint, que está dentro da classe? Qualquer um pode explicar isso para mim, por favor.
Raghavendra Gupta

Respostas:

394

Uma vez que estas são funções de membro, chamá-lo como uma função membro na instância, self.

def isNear(self, p):
    self.distToPoint(p)
    ...
Jeff Mercado
fonte
2
Mas tenha cuidado self.foo () usará a ordem de resolução do método que pode resolver uma função em uma classe diferente.
Francis Davey
O que acontece se não usarmos o eu? e chamar diretamente distToPoint (p)?
Marlon Abeykoon 16/08/16
3
@Marlon Abeykoon o "eu" argumento vai estar ausente
Pitipaty
1
E se isNear e distToPoint estiverem usando argumentos diferentes. Então, como podemos chamar distToPoint, que está dentro da classe? Qualquer um pode explicar isso para mim, por favor.
Raghavendra Gupta
46

Isso não funciona porque distToPointestá dentro de sua classe, então você precisa prefixo com o nome da classe, se você quiser se referir a ele, como este: classname.distToPoint(self, p). Você não deve fazer assim, no entanto. A melhor maneira do fazer é para referir o método directamente através da instância de classe (que é o primeiro argumento de um método de classe), assim: self.distToPoint(p).

Aleksi Torhamo
fonte
@Aleski. Se for um método genérico (comum a todas as instâncias e sem nenhuma variável específica da instância mencionada no método), você poderia explicar por que não se deve usar classname.distToPoint (self, p)?
Yugmorf
2
@Yugmorf: Existe apenas uma situação em que se deve usar classname.distToPoint(self, p): quando você está definindo uma subclasse que substitui distToPoint, mas precisa chamar o original. Se você tentasse ligar self.distToPoint(p)normalmente, nesse caso, acabaria chamando o método que está definindo e entraria em uma recursão infinita. Se não estiver dentro de uma classe, também há apenas uma situação em que você usaria em classname.distToPoint(obj, p)vez de obj.distToPoint(p): se obj pode ser uma instância da subclasse, mas você precisa chamar o original distToPointdefinido (continuação)
Aleksi Torhamo
1
em classnamevez da versão substituída na subclasse - mas nota que isso é muito hacky e não deve ser feito, em geral, sem muito boa razão. Observe que você quebra o polimorfismo de subtipo ao chamar um método explicitamente por meio de uma classe (nos dois exemplos acima, você deseja fazer isso especificamente ). Então, resumindo: você só deve chamar um método explicitamente através de uma classe quando precisar contornar o polimorfismo de subtipo por algum [bom] motivo. Se o método não foi substituído, as duas maneiras são iguais, mas self.distToPoint(p)são mais curtas e mais legíveis, (continuação) #
Aleksi Torhamo 10/10
então você definitivamente ainda deve usá-lo. Agora, chegando às especificidades da sua pergunta: se o seu método não usa nenhuma variável de instância, talvez seja um método de classe? Você faz isso adicionando @classmethodantes do método e depois disso não terá mais uma instância ( self) como o primeiro argumento - em vez disso, obtém a classe, portanto, deve nomear o primeiro argumento, por exemplo. clsem vez de. Depois disso, você pode ligar para o classmethod quer como obj.distToPoint(p)ou classname.distToPoint(p)(note a falta de obj). Você provavelmente ainda deve usar (continuação) #
Aleksi Torhamo 10/10
obj.distToPoint(p)no entanto, se você tiver apenas uma instância relevante em suas mãos, a menos que - novamente - você tenha algum [bom] motivo para contornar o polimorfismo de subtipo, pois o método de classe também poderia ter sido substituído em uma subclasse em geral. Obviamente, se você não tem uma instância relevante disponível, deve chamar o método de classe diretamente por meio de uma classe.
Aleksi Torhamo 10/10