self в Python — первый параметр метода, через который метод получает объект, у которого его вызвали. Передавать его руками не нужно: когда вы пишете rex.bark(), Python сам вызывает Dog.bark(rex) и кладёт rex в self. Через self.name метод читает и меняет данные именно этого объекта, а не соседнего.
Слово self не входит в список ключевых, это обычное имя параметра. Но PEP 8 требует писать именно его. Если классы пока в новинку, начните с разбора ООП на Python: там по порядку объяснено, что такое класс, объект и атрибут.
Как работает self на примере

Возьмём класс с двумя собаками. Метод bark у них один на двоих, а клички разные.
class Dog:
def __init__(self, name):
self.name = name
def bark(self):
return f"{self.name}: Гав!"
rex = Dog("Рекс")
bim = Dog("Бим")
print(rex.bark())
print(bim.bark())
print(Dog.bark(rex))
Строку в bark собирает f-строка: в фигурные скобки подставляется значение self.name. Вывод:
Рекс: Гав!
Бим: Гав!
Рекс: Гав!
Что происходит, когда вы пишете rex.bark():
- Python ищет
barkи находит его в классеDog, а не в самом объекте. - Метод вызван через
rex, поэтому интерпретатор подставляетrexпервым аргументом. - Внутри метода
selfуказывает наrex, иself.nameдаёт «Рекс». - При вызове
bim.bark()тот же код получает вselfдругой объект и возвращает «Бим».
Третья строка вывода показывает тот же вызов в развёрнутом виде: Dog.bark(rex) передаёт объект явно. В учебнике Python сказано то же самое: вызов x.f() полностью совпадает с MyClass.f(x).
Во всём остальном
selfведёт себя как обычный параметр функции. Необычен только способ передачи: объект в него подставляет точка в записиобъект.метод().
self в __init__: где хранятся данные объекта
Метод __init__ запускается при создании объекта, и self в нём указывает на объект, который только что появился. Всё, что вы запишете через self.атрибут, останется в объекте и после выхода из метода.
Без self. присваивание создаёт локальную переменную. Она исчезает, как только метод закончил работу:
class Wallet:
def __init__(self, balance):
self.balance = balance
def add_wrong(self, amount):
balance = self.balance + amount
def add(self, amount):
self.balance = self.balance + amount
w = Wallet(100)
w.add_wrong(50)
print(w.balance)
w.add(50)
print(w.balance)
100
150
Метод add_wrong посчитал сумму и тут же её потерял. Ошибки нет, а баланс не изменился, и программа спокойно работает дальше. Такой баг легко пропустить при проверке.
В FAQ по устройству Python это одна из причин явного self. Локальные переменные и атрибуты объекта живут в двух разных пространствах имён, и Python нужно сказать, в какое из них писать.
Посмотреть, что лежит в объекте, можно функцией vars():
class Dog:
def __init__(self, name):
self.name = name
self.tricks = []
rex = Dog("Рекс")
rex.tricks.append("сидеть")
print(vars(rex))
{'name': 'Рекс', 'tricks': ['сидеть']}
Атрибуты бывают двух видов, и путать их не стоит:
| Где объявлен | Как записан | Чей |
|---|---|---|
в методе через self |
self.name = name |
свой у каждого объекта |
| в теле класса | sound = "гав" |
общий для всех объектов класса |
Как спрятать такие данные от внешнего кода, рассказано в разделе про инкапсуляцию в статье о принципах ООП.
Канал основателя Checkroi Вани Буявца3 800 человек читают мой Телеграм-канал про нейросетиСобрал промпты для Claude Code и ChatGPT, разборы ИИ-инструментов и лайфхаки по продвижению бизнеса в одном местеПрисоединитьсяПочему self в Python пишут явно

В Java и C++ ссылка на текущий объект называется this и доступна внутри метода без объявления. Python устроен иначе: объект приходит обычным параметром, и его видно в сигнатуре каждого метода.
| Python | Java, C++ | |
|---|---|---|
| Имя | self, договорённость |
this, ключевое слово |
| Объявляется в методе | да, первым параметром | нет |
| Обращение к полю объекта | только self.name |
можно просто name |
В JavaScript this тоже не объявляют, но к полю, как и в Python, обращаются только через this.name.
Зачем так сделано, разработчики объясняют в официальном FAQ. Идею позаимствовали из языка Modula-3, а доводы такие:
- Читаемость. По записи
self.xсразу видно, что это атрибут объекта, а не локальная переменная, даже если определение класса вы не помните наизусть. - Вызов метода родителя. Метод базового класса вызывается как обычная функция,
Base.method(self, ...), и особый синтаксис вроде::из C++ не нужен. - Присваивание. Объявлений переменных в Python нет, поэтому интерпретатору нужен знак, что значение пишется в объект. Этим знаком служит
self.перед именем.
Можно ли назвать self по-другому
Можно. Для интерпретатора это обычное имя параметра, и синтаксис Python его выбор не ограничивает. Класс с this работает точно так же:
class Dog:
def __init__(this, name):
this.name = name
def bark(this):
return f"{this.name}: Гав!"
print(Dog("Рекс").bark())
Рекс: Гав!
В учебнике Python про это имя сказано прямо: «Это всего лишь общепринятая договорённость: имя self не имеет никакого особого значения в Python». Там же оговорка: другим программистам такой код может быть труднее читать.
Стандарт оформления PEP 8 требует всегда называть первый аргумент обычного метода self, а первый аргумент метода класса называть cls. Переименовывать не стоит: коллега, открыв ваш класс, будет каждый раз гадать, откуда взялся this.
self, cls и методы без них
Не каждому методу нужен объект. Видов методов в Python три, и первый параметр у них разный:
| Вид метода | Декоратор | Первый параметр | Когда нужен |
|---|---|---|---|
| обычный, метод экземпляра | нет | self, объект |
работа с данными конкретного объекта |
| метод класса | @classmethod |
cls, сам класс |
другие способы создать объект, общие настройки класса |
| статический | @staticmethod |
нет | вспомогательная функция, которой не нужны ни объект, ни класс |
Все три вида в одном классе:
class Temperature:
scale = "Цельсий"
def __init__(self, degrees):
self.degrees = degrees
def show(self):
return f"{self.degrees} °C"
@classmethod
def from_fahrenheit(cls, f):
return cls(round((f - 32) * 5 / 9, 1))
@staticmethod
def is_freezing(degrees):
return degrees <= 0
t = Temperature.from_fahrenheit(100)
print(t.show())
print(Temperature.is_freezing(-5))
print(t.scale)
37.8 °C
True
Цельсий
Метод from_fahrenheit получает в cls класс Temperature и создаёт через него объект. Если вызвать этот метод у класса-наследника, в cls придёт наследник, и объект получится его типа. Оба декоратора описаны в документации: classmethod и staticmethod.
self при наследовании
В наследнике self указывает на объект наследника, даже если код метода написан в родителе. Поэтому describe из класса Animal вызывает sound кошки:
class Animal:
def __init__(self, name):
self.name = name
def describe(self):
return f"{self.name} говорит {self.sound()}"
def sound(self):
return "..."
class Cat(Animal):
def sound(self):
return "мяу"
print(Cat("Мурка").describe())
Мурка говорит мяу
На этом построен полиморфизм: родитель задаёт общий порядок действий, наследники подменяют отдельные шаги. Версию метода из родителя вызывают через super().sound() или явно, Animal.sound(self).
Зачем методу возвращать self
Метод может отдать сам объект через return self. Тогда вызовы удобно писать цепочкой:
class Query:
def __init__(self):
self.parts = []
def where(self, condition):
self.parts.append(condition)
return self
def build(self):
return " AND ".join(self.parts)
sql = Query().where("age > 18").where("city = 'Казань'").build()
print(sql)
age > 18 AND city = 'Казань'
Каждый where дописывает условие в тот же объект и передаёт его следующему вызову. Во встроенных типах Python так почти не делают: методы, которые меняют объект на месте, возвращают None. Так устроен, например, метод sort() у списка.
Частые ошибки с self

Ниже пять ошибок, которые новички встречают чаще всего. Трейсбеки сняты в Python 3.14, путь к файлу сокращён до имени main.py.
Забыли self в объявлении метода
class Dog:
def bark():
return "Гав!"
Dog().bark()
Traceback (most recent call last):
File "main.py", line 6, in <module>
Dog().bark()
~~~~~~~~~~^^
TypeError: Dog.bark() takes 0 positional arguments but 1 was given
Python передал объект первым аргументом, а принять его метод не может: параметров у него ноль.
Решение: добавить self первым параметром, def bark(self):.
Вызвали метод у класса, а не у объекта
Traceback (most recent call last):
File "main.py", line 9, in <module>
Dog.bark()
~~~~~~~~^^
TypeError: Dog.bark() missing 1 required positional argument: 'self'
Здесь класс тот же, что в первом примере статьи, но вызов идёт через Dog, а не через собаку. Подставлять в self нечего.
Решение: сначала создать объект, Dog("Рекс").bark(). Если методу объект и правда не нужен, сделайте его статическим.
Обратились к атрибуту без self
Traceback (most recent call last):
File "main.py", line 9, in <module>
Dog("Рекс").bark()
~~~~~~~~~~~~~~~~^^
File "main.py", line 6, in bark
return f"{name}: Гав!"
^^^^
NameError: name 'name' is not defined. Did you mean: 'self.name'?
Внутри метода написали name вместо self.name. Подсказку «Did you mean: ‘self.name’?» интерпретатор выводит начиная с Python 3.12, в старых версиях будет только первая половина сообщения.
Решение: писать self.name везде, где нужен атрибут объекта.
Вызвали соседний метод без self
Traceback (most recent call last):
File "main.py", line 12, in <module>
Dog("Рекс").greet()
~~~~~~~~~~~~~~~~~^^
File "main.py", line 9, in greet
return bark()
^^^^
NameError: name 'bark' is not defined. Did you mean: 'self.bark'?
Метод greet вызвал bark() как обычную функцию. Но методы лежат в классе, и без self. Python ищет функцию с таким именем снаружи.
Решение: return self.bark().
Использовали self в теле класса
class Dog:
sound = self.name
Traceback (most recent call last):
File "main.py", line 1, in <module>
class Dog:
sound = self.name
File "main.py", line 2, in Dog
sound = self.name
^^^^
NameError: name 'self' is not defined
self существует только внутри метода, пока его вызывают. В теле класса объекта ещё нет, ссылаться не на что.
Решение: перенести присваивание в __init__: self.sound = .... Перехватывать такие ошибки во время работы программы помогает конструкция try except, но опечатку с self правят в самом коде: обработчик её только спрячет.
Где освоить Python системно
Разобраться с self по одной статье можно за вечер. Проектировать классы для настоящей программы учатся дольше: на задачах, ревью кода и собственных проектах. Если вы смотрите на Python как на работу, загляните в обзор профессии Python-разработчика.
Ниже курсы по Python из нашего каталога. Их можно сравнить по цене и длительности.
| Курс | Школа | Стоимость со скидкой | В рассрочку | Длительность | Обзор курса от Checkroi |
|---|---|---|---|---|---|
| Профессия «Python-разработчик» Перейти на сайт курса | 157 335 ₽ | 5987 ₽/мес. | 10 месяцев | Обзор курса | |
| Fullstack-разработчик на Python Перейти на сайт курса | 137 000 ₽ | 7125 ₽/мес. | 21 месяц | Обзор курса | |
| ДО Профессия Python-разработчик Перейти на сайт курса | 149 001 ₽ | 3167 ₽/мес. | 10 месяцев | Обзор курса | |
| Автоматизированное тестирование на Python Перейти на сайт курса | 118 754 ₽ | 4108 ₽/мес. | 9 месяцев | Обзор курса | |
| Профессия Python-разработчик Перейти на сайт курса | 140 040 ₽ | 3890 ₽/мес. | 10 месяцев | Обзор курса |
Больше программ — в полном каталоге курсов по Python




