Функция вызова Python в классе


242

У меня есть этот код, который рассчитывает расстояние между двумя координатами. Обе функции находятся в одном классе.

Однако как я могу вызвать функцию distToPointв функции 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
попробуйте: self.distToPoint (p)
momeara

Что если isNear и distToPoint принимают разные аргументы. Тогда как мы можем вызвать distToPoint, который находится внутри класса? Любой может объяснить это для меня, пожалуйста.
Рагхавендра Гупта

Ответы:


394

Поскольку это функции-члены, вызовите его как функцию-член в экземпляре self.

def isNear(self, p):
    self.distToPoint(p)
    ...

2
Но будьте осторожны. Self.foo () будет использовать порядок разрешения методов, который может разрешаться для функции в другом классе.
Фрэнсис Дейви

Что произойдет, если мы не будем использовать себя? и напрямую вызывать distToPoint (p)?
Марлон Абейкун

3
@Marlon Abeykoon «я» аргумент будет отсутствовать
Питипаты

1
Что если isNear и distToPoint принимают разные аргументы. Тогда как мы можем вызвать distToPoint, который находится внутри класса? Любой может объяснить это для меня, пожалуйста.
Рагхавендра Гупта

46

Это не работает , потому что distToPointнаходится внутри вашего класса, так что вам нужно префикс с именем класса , если вы хотите , чтобы обратиться к нему, как это: classname.distToPoint(self, p). Вы не должны делать это так, хотя. Лучший способ сделать это состоит в ссылку к методу непосредственно через экземпляр класса (который является первым аргументом метода класса), например , так: self.distToPoint(p).


@Aleski. Если это универсальный метод (общий для всех экземпляров и без каких-либо специфических переменных экземпляра, на которые есть ссылки в методе), не могли бы вы объяснить, почему нельзя использовать classname.distToPoint (self, p)?
Югморф

2
@Yugmorf: есть только одна ситуация, в которой следует использовать classname.distToPoint(self, p): когда вы определяете подкласс, который переопределяет distToPoint, но должен вызывать оригинал. Если вы попытаетесь вызвать self.distToPoint(p)как обычно в этом случае, вы в конечном итоге вызовете метод, который вы только что определили, и попадете в бесконечную рекурсию. Если не внутри класса, есть также только одна ситуация, в которой вы бы использовали classname.distToPoint(obj, p)вместо obj.distToPoint(p): если obj может быть экземпляром подкласса, но вам нужно вызвать исходный distToPointопределенный (продолжение)
Алекси Торхамо

1
в classnameвместо перегруженной версии в подклассе - но учтите , что это очень Hacky и не должно быть сделано вообще без очень уважительной причины. Обратите внимание, что вы нарушаете полиморфизм подтипа, когда вызываете метод явно через класс (в обоих приведенных выше примерах вы специально хотите это сделать). Короче говоря: вы должны вызывать метод только через класс, когда вам нужно обойти полиморфизм подтипа по какой-либо [веской] причине. Если метод не был переопределен, оба пути одинаковы, но они self.distToPoint(p)короче и более читабельны, (продолжение)
Алекси Торхамо,

так что вам определенно стоит его использовать. Теперь перейдем к специфике вашего вопроса: если ваш метод не использует какие-либо переменные экземпляра, может быть, вместо него должен использоваться метод класса? Вы делаете это, добавляя @classmethodперед методом, и после этого вы больше не получите instance ( self) в качестве первого аргумента - вместо этого вы получаете класс, поэтому вы должны назвать первый аргумент, например. clsвместо. После этого вы можете вызывать метод класса либо как, obj.distToPoint(p)либо classname.distToPoint(p)(обратите внимание на отсутствие obj). Вы все еще должны, вероятно, использовать (продолжение)
Алекси Торхамо

obj.distToPoint(p)тем не менее, если у вас в руках только соответствующий экземпляр, если - опять же - у вас нет [веских] причин обойти полиморфизм подтипа, поскольку метод класса мог бы быть переопределен и в подклассе в целом. Конечно, если у вас нет соответствующего экземпляра, вы должны непременно вызвать метод класса напрямую через класс.
Алекси Торхамо
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.