Объект self: как работать с ним в методах

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

Основы работы с self

Ключевое слово self в Python представляет собой ссылку на текущий экземпляр класса. Оно используется в методах для доступа к атрибутам и другим методам этого экземпляра. Без self невозможно различить, с каким именно объектом работает метод. Рассмотрим наиболее эффективное и распространённое применение.

Самый распространённый способ - явно указать self первым параметром каждого метода экземпляра. Это позволяет обращаться к полям объекта через self.атрибут.


class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def introduce(self):
        return f"Меня зовут {self.name}, мне {self.age} лет."

p = Person("Анна", 25)
print(p.introduce())

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

Меня зовут Анна, мне 25 лет.

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

В конструкторе __init__ через self создаются атрибуты экземпляра. Метод introduce использует self.name и self.age для формирования строки. При вызове p.introduce() Python автоматически передаёт объект p в параметр self.

Типичная ошибка:

Забыть указать self в определении метода. Это приводит к TypeError при вызове, так как метод получает лишний аргумент.


class Bad:
    def method():  # нет self
        print("Ошибка")

obj = Bad()
try:
    obj.method()
except TypeError as e:
    print(e)

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

method() takes 0 positional arguments but 1 was given

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

Решение: всегда добавлять self как первый параметр в методы экземпляра.

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

Python не требует строго имени self. Можно использовать любое другое (например, this, me). Однако это нарушает общепринятые соглашения (PEP 8) и делает код менее читаемым.


class Example:
    def __init__(this, value):  # нестандартное имя
        this.value = value

    def show(me):
        return me.value

e = Example(42)
print(e.show())

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

42

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

Код работает, но его сложнее понимать другим разработчикам. Рекомендуется придерживаться self.

Как организовать работу с методами, не требующими экземпляра?

Иногда метод не использует self - например, для служебной логики, не зависящей от объекта. В таких случаях применяются staticmethod и classmethod.

Что такое метод класса (classmethod)?

Метод класса принимает первым параметром сам класс (cls), а не экземпляр. Он помещается декоратором @classmethod.


class MyClass:
    count = 0

    def __init__(self):
        MyClass.count += 1

    @classmethod
    def get_count(cls):
        return cls.count

obj1 = MyClass()
obj2 = MyClass()
print(MyClass.get_count())

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

2

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

Здесь cls - это сам класс MyClass. Метод get_count вызывается как MyClass.get_count() или даже obj1.get_count(), но в обоих случаях первым аргументом передаётся класс.

Как объявить статический метод (staticmethod)?

Статический метод не принимает ни self, ни cls. Он ведёт себя как обычная функция, но лежит в пространстве имён класса.


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

print(MathUtils.add(3, 4))

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

7

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

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

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

В Python, в отличие от Java или C++, не существует неявного this. Для доступа к текущему объекту необходимо явно использовать первый параметр. Однако можно вызывать методы, передавая экземпляр как обычный аргумент:


class A:
    def method(self):
        print("Метод вызван")

a = A()
A.method(a)  # явная передача экземпляра

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

Метод вызван

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

Этот приём иногда помогает лучше понять, как работает передача self, но на практике обычно используется запись a.method().

Проблема с изменяемыми атрибутами:

Если атрибут является изменяемым объектом (список, словарь), его изменение через self влияет на экземпляр. Это ожидаемо, но иногда приводит к путанице.


class Stack:
    def __init__(self):
        self.items = []

    def push(self, item):
        self.items.append(item)

    def pop(self):
        return self.items.pop()

s = Stack()
s.push(1)
s.push(2)
print(s.pop())

Self method python (параметр self в методах python)

2

приватные атрибуты python (приватные атрибуты в python)

Ошибок нет, но если по ошибке присвоить self.items = self.items + [item] - создастся новый список, а не модифицируется существующий. Важно различать мутацию и переназначение.

Когда self не нужен?

В некоторых специальных методах, таких как __new__, self не передаётся, потому что экземпляр ещё не создан. Вместо этого используется cls. А в статических и классовых методах, как уже обсуждалось, self отсутствует по определению.

Ошибка при попытке использовать self в статическом методе:

При добавлении self в статический метод Python не вызовет ошибку автоматически, но это нарушает соглашения. Если такой метод всё же определён с self, он станет обычным методом экземпляра, что может привести к неожиданностям.


class Wrong:
    @staticmethod
    def method(self):  # неправильное использование
        print(self)

w = Wrong()
try:
    w.method()
except TypeError as e:
    print(e)

создание типов python (создание пользовательских типов данных в python)

method() got multiple values for argument 'self'

Здесь декоратор @staticmethod игнорирует self как первый параметр, но при вызове через экземпляр Python пытается передать объект дважды (явно и неявно). Нужно либо убрать self, либо не вешать декоратор.

- Get set python (геттеры и сеттеры в python)
- Python имя метода (имя метода в python)
- Python print self (использование self в print python)

Расширенные примеры работы с self

1. Использование self в магическом методе __repr__

Метод __repr__ возвращает строковое представление объекта. Через self можно получать значения атрибутов для отладки.

Пример

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

    def __repr__(self):
        return f"Point(x={self.x}, y={self.y})"

p = Point(3, 4)
print(p)
Point(x=3, y=4)

2. Цепочка вызовов методов через возврат self

Если метод возвращает self, можно вызывать несколько методов подряд (fluent interface).

Пример

class Query:
    def __init__(self):
        self._conditions = []

    def filter(self, condition):
        self._conditions.append(condition)
        return self

    def sort(self, key):
        self._sort_key = key
        return self

    def execute(self):
        return f"Сортировка: {getattr(self, '_sort_key', 'нет')}, фильтры: {self._conditions}"

q = Query()
result = q.filter("age > 18").sort("name").execute()
print(result)
Сортировка: name, фильтры: ['age > 18']

3. Получение класса экземпляра через self.__class__

Атрибут self.__class__ возвращает класс объекта. Это полезно для создания копий или доступа к классовым атрибутам.

Пример

class Car:
    wheels = 4

    def info(self):
        return f"Это {self.__class__.__name__} с {self.wheels} колёсами"

class Truck(Car):
    wheels = 6

c = Car()
t = Truck()
print(c.info())
print(t.info())
Это Car с 4 колёсами
Это Truck с 6 колёсами

4. Применение self в дескрипторах для доступа к атрибутам

Дескриптор - объект, который управляет доступом к атрибуту. Методы __get__, __set__ принимают self (сам дескриптор) и instance (экземпляр, к атрибуту которого обращаются).

Пример

class PositiveNumber:
    def __init__(self, name):
        self.name = name

    def __get__(self, instance, owner):
        return instance.__dict__.get(self.name)

    def __set__(self, instance, value):
        if value < 0:
            raise ValueError("Значение должно быть положительным")
        instance.__dict__[self.name] = value

class Order:
    quantity = PositiveNumber("quantity")

    def __init__(self, quantity):
        self.quantity = quantity

o = Order(10)
print(o.quantity)
try:
    o.quantity = -5
except ValueError as e:
    print(e)
10
Значение должно быть положительным

5. self в методе __init__subclass__ для проверки подклассов

Метаклассы и хуки создания классов используют cls, но иногда через self (точнее, через экземпляр) можно получить доступ к метаклассу. Более показательный пример - использование self в магическом методе __init_subclass__, который вызывается при создании подкласса. Он принимает cls, но внутри может обращаться к super().__init_subclass__, где нет self. Однако рассмотрим другой случай: метод __del__, который вызывается при удалении объекта.

Пример

class Resource:
    def __init__(self):
        self.handle = open("/dev/null", "w")

    def __del__(self):
        self.handle.close()
        print("Ресурс освобождён")

r = Resource()
del r
Ресурс освобождён

6. Создание синглтона через self и __new__

Метод __new__ создаёт экземпляр, получая первым аргументом класс (cls), а не self. Однако внутри __new__ можно управлять тем, какой объект вернуть. Классический синглтон:

Пример

class Singleton:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

    def __init__(self):
        self.value = 0

a = Singleton()
b = Singleton()
print(a is b)  # True
True

Объект self в Python - comments

En
Self object python (python)