self в Python: от основ до нюансов объектно-ориентированного программирования

Раздел: Объектно-ориентированное программирование -> Объектно-ориентированное программирование

Основная концепция self

Параметр self является обязательным первым параметром любого метода экземпляра класса. Он представляет собой ссылку на конкретный объект (экземпляр), для которого вызывается метод. При вызове метода через объект Python автоматически передает сам объект в качестве первого аргумента.


class MyClass:
    def method(self, arg):
        print(f"Метод вызван для {self}, аргумент {arg}")

obj = MyClass()
obj.method(10)
  

атрибуты класса python (атрибуты классов и объектов в python)

Метод вызван для <__main__.MyClass object at 0x...>, аргумент 10
  

библиотека классов python (библиотека классов в python)

Без использования self невозможно обратиться к атрибутам и другим методам данного экземпляра внутри класса.

Можно ли использовать другое имя вместо self?

Да, self не является ключевым словом, а лишь общепринятым соглашением. Можно назвать параметр любым именем, например this или myself. Однако отступление от стандарта ухудшает читаемость кода.


class Example:
    def __init__(this, value):
        this.value = value
    def show(myself):
        print(myself.value)
  

метод объекта python (методы объектов в python)

Такой код будет работать, но не рекомендуется.

Проблема: при переименовании self сложнее понимать код другим разработчикам. IDE могут не подсвечивать правильно.

Как обойтись без self в методе? (статические методы)

Если метод не нуждается в доступе к экземпляру, его объявляют статическим с помощью декоратора @staticmethod. В этом случае параметр self не передаётся.


class Calculator:
    @staticmethod
    def add(a, b):
        return a + b

print(Calculator.add(5, 3))
  

метод call python (метод __call__ в python)

8

Python структура объекта (структура объекта в python)

Статические методы используются для вспомогательных функций, логически принадлежащих классу.

Зачем нужен cls вместо self? (классовые методы)

Для методов, работающих с классом в целом, применяется декоратор @classmethod. Первым параметром передаётся класс (cls), а не экземпляр.


class MyClass:
    count = 0
    def __init__(self):
        MyClass.count += 1
    @classmethod
    def get_count(cls):
        return cls.count
  

Python создание объектов (создание объектов в python)


a = MyClass()
b = MyClass()
print(MyClass.get_count())
  

Self object python (объект self в python)

2

Object attribute python (атрибуты объекта в python)

Классовые методы часто используются для фабричных методов.

Как self используется в конструкторе? (магические методы)

Параметр self обязателен и в методе __init__. Через него устанавливаются начальные атрибуты экземпляра.


class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __str__(self):
        return f"{self.name}, {self.age} лет"
  

Python call method (вызов метода в python)


p = Person("Алиса", 30)
print(p)
  

Python класс данных (класс данных в python)

Алиса, 30 лет

Class method python (методы классов в python)

Помимо __init__, self используется в __repr__, __eq__ и других магических методах.

Как возвращать self для цепочки вызовов?

Методы могут возвращать self, чтобы обеспечить последовательный вызов нескольких методов на одном объекте (fluent interface).


class Builder:
    def __init__(self):
        self.parts = []
    def add_part(self, part):
        self.parts.append(part)
        return self
    def build(self):
        print("Собрано:", ", ".join(self.parts))

b = Builder()
b.add_part("Колесо").add_part("Двигатель").build()
  

Python object methods (методы объектов в python)

Собрано: Колесо, Двигатель

класс python определение (определение классов в python)

Каждый метод возвращает self, позволяя вызывать следующий метод через точку.

Типичные ошибки и их решение

Забыли self в определении метода:


class Bad:
    def method(arg):  # нет self
        print(arg)
  

При вызове obj.method(10) возникает ошибка TypeError: method() takes 1 positional argument but 2 were given, потому что экземпляр передаётся как первый аргумент, а метод ожидает один. Решение: добавить self.

Передача self явно: Иногда новички пишут obj.method(obj, arg), что приводит к двойной передаче экземпляра. Достаточно вызвать метод с одним аргументом, self передаётся автоматически.

Путаница между self и cls: В классовых методах первый параметр - cls, а не self. Если ошибочно написать self, то при обращении к self внутри классового метода будет ошибка атрибута.

- создание типов python (создание пользовательских типов данных в python)
- список атрибутов python (список атрибутов объекта в python)
- тип данных класса python (тип данных класса в python)

Расширенные примеры использования self

Пример 1: Явный вызов метода родителя через self

Пример

class Parent:
    def show(self):
        print("Parent.show")

class Child(Parent):
    def show(self):
        Parent.show(self)  # явная передача self
        print("Child.show")

c = Child()
c.show()
Parent.show
Child.show

В этом примере метод дочернего класса вызывает метод родителя, передавая self вручную. Альтернативой служит super().show(), но явная передача self иногда применяется при множественном наследовании.

Пример 2: self в контекстном менеджере (__enter__ / __exit__)

Пример

class FileManager:
    def __init__(self, filename):
        self.filename = filename

    def __enter__(self):
        self.file = open(self.filename, 'w')
        return self.file

    def __exit__(self, exc_type, exc_value, traceback):
        self.file.close()

with FileManager('test.txt') as f:
    f.write('Hello')

Здесь self хранит имя файла и сам файловый объект. Метод __enter__ возвращает объект файла, а __exit__ закрывает его.

Пример 3: self в декорированном методе (логирование вызовов)

Пример

import functools

def log_call(func):
    @functools.wraps(func)
    def wrapper(self, *args, **kwargs):
        print(f"Вызов {func.__name__} для {self}")
        return func(self, *args, **kwargs)
    return wrapper

class MyClass:
    @log_call
    def do_something(self, value):
        self.value = value

obj = MyClass()
obj.do_something(42)
print(obj.value)
Вызов do_something для <__main__.MyClass object at 0x...>
42

Декоратор log_call принимает метод с первым параметром self, что позволяет получить доступ к экземпляру внутри обёртки.

Пример 4: self в property с геттером и сеттером

Пример

class Circle:
    def __init__(self, radius):
        self._radius = radius

    @property
    def radius(self):
        return self._radius

    @radius.setter
    def radius(self, value):
        if value < 0:
            raise ValueError("Радиус не может быть отрицательным")
        self._radius = value

    @property
    def area(self):
        return 3.14159 * self._radius ** 2

c = Circle(5)
print(c.radius, c.area)
c.radius = 10
print(c.area)
5 78.53975
314.159

Свойства (property) используют self для доступа к атрибутам экземпляра. Сеттер выполняет проверку перед изменением.

Пример 5: self в методе, возвращающем новый объект (неизменяемое копирование)

Пример

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def move(self, dx, dy):
        return Point(self.x + dx, self.y + dy)

p1 = Point(0, 0)
p2 = p1.move(5, -3)
print(p2.x, p2.y)  # 5 -3
5 -3

Метод move не изменяет исходный объект, а создаёт новый на основе self, что характерно для неизменяемых типов.

Параметр self в методах Python - comments

En
Self method python (python)