← Назад к вопросам
Зачем в __init__ передается ссылка на первым параметром?
1.6 Junior🔥 141 комментариев
#Python Core
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Зачем в init передается ссылка на первым параметром?
В Python первый параметр метода init (по соглашению называемый self) — это ссылка на текущий экземпляр объекта. Он позволяет методу получить доступ к атрибутам и другим методам того же объекта. Это фундаментальный механизм, который делает объектно-ориентированное программирование в Python возможным.
Понимание self
class Person:
def __init__(self, name, age):
# self — это ссылка на конкретный объект
self.name = name # Сохраняем имя в атрибут объекта
self.age = age # Сохраняем возраст в атрибут объекта
print(f"Создан объект Person: {id(self)}")
def introduce(self):
# self используется для доступа к атрибутам объекта
return f"Привет, я {self.name}, мне {self.age} лет"
# При создании объекта
person1 = Person("Иван", 30) # Печатает: Создан объект Person: 140342851234512
person2 = Person("Мария", 25) # Печатает: Создан объект Person: 140342851234560
print(person1.introduce()) # self = person1 -> "Привет, я Иван, мне 30 лет"
print(person2.introduce()) # self = person2 -> "Привет, я Мария, мне 25 лет"
Как Python передает self автоматически
class Counter:
def __init__(self, start=0):
self.value = start
def increment(self):
self.value += 1
# Когда мы пишем:
counter = Counter(10)
counter.increment()
# Python делает следующее:
# 1. counter = Counter(10)
# -> Python создает новый объект
# -> Python передает его как self в __init__
# -> self = <объект Counter>
# -> self.value = 10
# 2. counter.increment()
# -> Python передает counter как self в метод increment
# -> self = counter
# -> self.value += 1
# -> counter.value становится 11
print(counter.value) # 11
Без self (как это работало бы без Python)
# ❌ КАК БЫ БЫЛ БЕЗ PYTHON (НИЗКОУРОВНЕВЫЙ КОД)
class PersonWithoutSelf:
pass
# Если бы пришлось передавать объект вручную
person = PersonWithoutSelf()
# Пришлось бы передавать объект во все методы
def init(obj, name, age):
obj.name = name
obj.age = age
def introduce(obj):
return f"Привет, я {obj.name}, мне {obj.age} лет"
# Использование
init(person, "Иван", 30)
print(introduce(person)) # Очень неудобно!
# ✅ С PYTHON И self (ВЫСОКОУРОВНЕВЫЙ КОД)
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def introduce(self):
return f"Привет, я {self.name}, мне {self.age} лет"
# Использование
person = Person("Иван", 30)
print(person.introduce()) # Намного удобнее!
self хранит состояние объекта
class BankAccount:
def __init__(self, owner, balance):
self.owner = owner # Атрибут объекта
self.balance = balance # Атрибут объекта
def deposit(self, amount):
self.balance += amount # Изменяем состояние THIS объекта
def withdraw(self, amount):
if self.balance >= amount:
self.balance -= amount
else:
print("Недостаточно средств")
# Каждый объект имеет свое состояние
account1 = BankAccount("Иван", 1000)
account2 = BankAccount("Мария", 2000)
account1.deposit(500) # self = account1, balance становится 1500
account2.withdraw(200) # self = account2, balance становится 1800
print(account1.balance) # 1500 (состояние account1)
print(account2.balance) # 1800 (состояние account2)
print(account1 is account2) # False (разные объекты)
self явно и неявно
class Student:
def __init__(self, name, grade):
# ЯВНОЕ использование self
self.name = name
self.grade = grade
def get_info(self):
# ЯВНОЕ использование self
return f"{self.name} ({self.grade} класс)"
def study(self):
# НЕЯВНОЕ использование self
# Python передаёт self автоматически
print(f"{self.name} учится")
# Явное (через точку)
student = Student("Петр", 10)
print(student.get_info()) # Python передает student как self
# Явное (через класс)
Student.get_info(student) # Можно вызвать метод класса, явно передав объект
print(Student.get_info(student)) # Петр (10 класс)
Различие между переменной экземпляра и локальной переменной
class Example:
def __init__(self, value):
# self.value — ПЕРЕМЕННАЯ ЭКЗЕМПЛЯРА (атрибут объекта)
# Доступна везде в объекте
self.value = value
# local_var — ЛОКАЛЬНАЯ ПЕРЕМЕННАЯ
# Существует только в этом методе
local_var = value * 2
print(local_var) # 20 (если value = 10)
def show_value(self):
# Можно обратиться к self.value
print(self.value) # Работает (100)
# Но local_var недоступна
# print(local_var) # NameError: name 'local_var' is not defined
example = Example(10)
example.show_value() # Печатает 10
# Доступ к переменной экземпляра снаружи
print(example.value) # 10 (доступна через объект)
self в разных контекстах
class Calculator:
def __init__(self, initial=0):
self.result = initial
def add(self, x):
self.result += x
return self # Возвращаем self для цепочки вызовов
def multiply(self, x):
self.result *= x
return self # Для паттерна Method Chaining
@classmethod
def from_string(cls, value_str):
# В classmethod используется cls, а не self
return cls(int(value_str))
@staticmethod
def is_positive(x):
# В staticmethod нет ни self, ни cls
return x > 0
# Использование
calc = Calculator(10)
result = calc.add(5).multiply(2).add(10)
print(calc.result) # 40 (10 + 5 = 15, 15 * 2 = 30, 30 + 10 = 40)
# classmethod
calc2 = Calculator.from_string("20") # cls = Calculator
print(calc2.result) # 20
# staticmethod
print(Calculator.is_positive(5)) # True (не требует объекта)
Сравнение self в разных языках
# PYTHON
class Python:
def method(self):
print(self) # self — явно указано
# JAVA / C# / C++ — this
public class Java {
public void method() {
System.out.println(this); // this — явно указано (но скрыто по умолчанию)
}
}
# JAVASCRIPT — this
class JavaScript {
method() {
console.log(this); // this — явно указано
}
}
# В Python self ОБЯЗАТЕЛЕН в параметрах,
# в других языках это часто неявно
Ошибки с self
# ❌ Ошибка 1: забыли self
class WrongClass:
def __init__(name, age): # Забыли self!
name = name
age = age
obj = WrongClass("Иван", 30)
# TypeError: __init__() takes 2 positional arguments but 3 were given
# "Иван" становится self, а 30 становится name!
# ✅ Правильно
class RightClass:
def __init__(self, name, age):
self.name = name
self.age = age
# ❌ Ошибка 2: использовали self в staticmethod
class WrongStatic:
@staticmethod
def static_method(self, x): # НЕПРАВИЛЬНО!
return self.x # AttributeError
# ✅ Правильно
class RightStatic:
@staticmethod
def static_method(x): # Никакого self
return x * 2
print(RightStatic.static_method(5)) # 10
# ❌ Ошибка 3: забыли вызвать метод через объект
class MyClass:
def __init__(self):
self.value = 10
def get_value(self):
return self.value
obj = MyClass()
# MyClass.get_value() # TypeError: get_value() missing 1 required positional argument: 'self'
# Нужно передать объект
obj.get_value() # Правильно
# или MyClass.get_value(obj) # Тоже правильно
Заключение
self — это фундаментальный механизм Python, который позволяет:
- Получить доступ к состоянию объекта — каждый экземпляр имеет свои атрибуты
- Вызывать другие методы объекта — self.method()
- Различать объекты — self указывает на конкретный объект
При создании экземпляра класса Python автоматически передает созданный объект как первый параметр в метод. Это позволяет методам работать с состоянием именно этого объекта, а не какого-то другого. Без self объектно-ориентированное программирование в Python было бы невозможно.