Давайте возьмем простой векторный класс:
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
Мы хотим иметь метод, который вычисляет длину. Как бы это выглядело, если бы мы хотели определить его внутри класса?
def length(self):
return math.sqrt(self.x ** 2 + self.y ** 2)
Как должно выглядеть, когда мы определяем его как глобальный метод / функцию?
def length_global(vector):
return math.sqrt(vector.x ** 2 + vector.y ** 2)
Таким образом, вся структура остается прежней. Как я могу использовать это? Если мы на мгновение предположим, что мы не написали length
метод для нашего Vector
класса, мы могли бы сделать это:
Vector.length_new = length_global
v = Vector(3, 4)
print(v.length_new()) # 5.0
Это работает, потому что первый параметр length_global
можно повторно использовать в качестве параметра self
в length_new
. Это было бы невозможно без явного self
.
Еще один способ понять необходимость явного self
- посмотреть, где Python добавляет немного синтаксического сахара. Если иметь в виду, что в основном это звонок типа
v_instance.length()
внутренне преобразуется в
Vector.length(v_instance)
Легко увидеть, куда входит self
. На самом деле вы не пишете методы экземпляра в Python; то, что вы пишете, это методы класса, которые должны принимать экземпляр в качестве первого параметра. И, следовательно, вам придется явно указать параметр экземпляра где-нибудь.