← Назад к вопросам

Что такое self?

1.3 Junior🔥 201 комментариев
#Python

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое self?

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

Это не ключевое слово, просто соглашение по именованию, хотя его нарушение будет вызывать ошибки.

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

Когда ты создаёшь класс и вызываешь метод на объекте, Python автоматически передаёт этот объект в качестве первого аргумента методу:

class Dog:
    def __init__(self, name):
        self.name = name  # self — это текущий объект
    
    def bark(self):
        print(f"{self.name} goes woof!")  # self указывает на конкретную собаку

# Создаём объекты
dog1 = Dog("Buddy")
dog2 = Dog("Max")

# Вызываем методы
dog1.bark()  # Output: Buddy goes woof!
dog2.bark()  # Output: Max goes woof!

# Это эквивалентно:
# Dog.bark(dog1)  # явно передаём объект
# Dog.bark(dog2)

Ключевой момент: без self методы не знали бы, какому объекту принадлежит данные.

Как Python отправляет self

Когда ты пишешь dog1.bark(), Python делает следующее:

  1. Ищет класс объекта dog1 (класс Dog)
  2. Находит метод bark в классе
  3. Автоматически передаёт dog1 в качестве первого аргумента методу

Это называется method binding — связывание метода с объектом.

class Person:
    def __init__(self, name):
        self.name = name
    
    def greet(self):
        return f"My name is {self.name}"

person = Person("Alice")

# Эти два вызова эквивалентны:
print(person.greet())         # Python сам передаёт person
print(Person.greet(person))   # явное передание person

# Output в обоих случаях: My name is Alice

Атрибуты экземпляра через self

self используется для:

  1. Инициализации атрибутов в конструкторе:
class BankAccount:
    def __init__(self, owner, balance=0):
        self.owner = owner        # атрибут экземпляра
        self.balance = balance    # атрибут экземпляра

account1 = BankAccount("Alice", 1000)
account2 = BankAccount("Bob", 500)

print(account1.owner)    # Alice
print(account2.owner)    # Bob
print(account1.balance)  # 1000
print(account2.balance)  # 500
  1. Чтения и модификации атрибутов в методах:
class Counter:
    def __init__(self):
        self.count = 0
    
    def increment(self):
        self.count += 1  # читаем и изменяем атрибут через self
    
    def get_value(self):
        return self.count  # читаем атрибут через self

counter = Counter()
counter.increment()
counter.increment()
print(counter.get_value())  # Output: 2
  1. Вызова других методов этого же объекта:
class Calculator:
    def __init__(self, value=0):
        self.value = value
    
    def add(self, x):
        self.value += x
        self._log_operation(f"added {x}")
    
    def _log_operation(self, operation):
        print(f"Operation: {operation}, Current value: {self.value}")

calc = Calculator(10)
calc.add(5)  # вызывает add, который вызывает _log_operation через self

self vs переменные класса

Важное различие между атрибутами экземпляра и атрибутами класса:

class Car:
    wheels = 4  # переменная класса (общая для всех экземпляров)
    
    def __init__(self, brand):
        self.brand = brand  # переменная экземпляра (своя для каждого объекта)

car1 = Car("Toyota")
car2 = Car("Honda")

print(car1.brand)   # Toyota (своя для каждого объекта)
print(car2.brand)   # Honda

print(car1.wheels)  # 4 (общая переменная класса)
print(car2.wheels)  # 4 (одна и та же)

Car.wheels = 5  # изменим переменную класса
print(car1.wheels)  # 5 (изменилось для всех объектов)
print(car2.wheels)  # 5

Практический пример: class для работы с данными

class DataProcessor:
    def __init__(self, data_source):
        self.data_source = data_source
        self.processed_data = None
        self.error = None
    
    def load_data(self):
        try:
            # загружаем данные из источника
            self.processed_data = load_from_source(self.data_source)
            print(f"Loaded {len(self.processed_data)} records")
        except Exception as e:
            self.error = str(e)
            print(f"Error loading data: {self.error}")
    
    def filter_data(self, column, value):
        if self.processed_data is None:
            print("Data not loaded. Call load_data() first")
            return
        # используем self для работы с данными объекта
        self.processed_data = [
            row for row in self.processed_data 
            if row[column] == value
        ]
        print(f"Filtered to {len(self.processed_data)} records")
    
    def get_result(self):
        return self.processed_data if self.error is None else None

# Использование
processor1 = DataProcessor("database1.csv")
processor1.load_data()
processor1.filter_data("status", "active")
result = processor1.get_result()

processor2 = DataProcessor("database2.csv")  # отдельный объект
processor2.load_data()
processor2.filter_data("status", "pending")

self в различных типах методов

1. Методы экземпляра (regular methods)

class MyClass:
    def instance_method(self):
        # self — это экземпляр класса
        print(type(self))  # <class __main__.MyClass>

2. Методы класса (class methods) — первый аргумент cls

class MyClass:
    count = 0
    
    def __init__(self):
        MyClass.count += 1
    
    @classmethod
    def get_instance_count(cls):
        # cls — это сам класс, не экземпляр
        return cls.count

obj1 = MyClass()
obj2 = MyClass()
print(MyClass.get_instance_count())  # Output: 2

3. Статические методы — без self или cls

class MyClass:
    @staticmethod
    def static_method():
        # нет доступа к экземпляру или классу
        return "I am static"

print(MyClass.static_method())  # Output: I am static

Частые ошибки

# ❌ Ошибка 1: забыли self в методе
class Person:
    def __init__(self, name):
        self.name = name
    
    def greet():  # забыли self!
        return f"Hello, {self.name}"  # NameError: self not defined

# ❌ Ошибка 2: забыли self при вызове метода
class Person:
    def __init__(self, name):
        self.name = name

person = Person("Alice")
person.name = "Bob"
print(Person.name)  # AttributeError: type object Person has no attribute name

# ✅ Правильно:
print(person.name)  # Bob

Ключевые выводы

  • self — это ссылка на текущий экземпляр объекта
  • Python автоматически передаёт объект как первый аргумент методу
  • self нужен для доступа к атрибутам и методам конкретного объекта
  • Без self все объекты класса не смогли бы иметь независимые данные
  • Это основа объектно-ориентированного программирования в Python
Что такое self? | PrepBro