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

В чем разница между методом и инстансом класса?

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

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

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

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

Метод класса vs Инстанс класса: полное объяснение

Это две разные категории в Python. Не путай их с обычным методом инстанса — это совсем другое.

1. Три типа методов в Python

class MyClass:
    class_variable = "shared"
    
    # 1. ИНСТАНС МЕТОД (instance method)
    def instance_method(self):
        print(f"Инстанс метод, self={self}")
        return self.class_variable
    
    # 2. МЕТОД КЛАССА (class method)
    @classmethod
    def class_method(cls):
        print(f"Метод класса, cls={cls}")
        return cls.class_variable
    
    # 3. СТАТИЧЕСКИЙ МЕТОД (static method)
    @staticmethod
    def static_method():
        print("Статический метод")
        return "не имеет доступа к self или cls"

# Использование
obj = MyClass()
obj.instance_method()      # Вызвали через инстанс
MyClass.class_method()     # Вызвали через класс
MyClass.static_method()    # Можно вызвать оба способа

2. Инстанс метод (Instance Method)

Что это:

  • Получает первый параметр self (ссылка на конкретный объект)
  • Может менять состояние инстанса
  • Каждый инстанс имеет свои данные
class User:
    def __init__(self, name, age):
        self.name = name  # Данные инстанса
        self.age = age
    
    def greet(self):  # Инстанс метод
        return f"Привет, я {self.name}"
    
    def have_birthday(self):
        self.age += 1  # Меняем состояние инстанса
        return f"{self.name} теперь {self.age} лет"

alice = User("Alice", 30)
bob = User("Bob", 25)

print(alice.greet())  # "Привет, я Alice"
print(bob.greet())    # "Привет, я Bob"

print(alice.have_birthday())  # "Alice теперь 31 лет"
print(bob.age)                # 25 (не изменился)

Как это работает под капотом:

class User:
    def greet(self):
        return f"Привет, я {self.name}"

alice = User("Alice")

# Это две разные нотации, одно и то же:
alice.greet()           # Неявно передаёт alice как self
User.greet(alice)       # Явно передаёт alice

print(alice.greet == User.greet)  # False (разные объекты)
print(alice.greet())              # Bound method (привязан к объекту)
print(User.greet)                 # Unbound function (не привязана)

3. Метод класса (Class Method)

Что это:

  • Получает первый параметр cls (ссылка на сам класс, не инстанс)
  • Может менять состояние класса
  • Все инстансы видят эти изменения
  • Используется для создания alternative constructors
class Person:
    count = 0  # Переменная класса
    
    def __init__(self, name):
        self.name = name
        Person.count += 1  # Увеличиваем счётчик класса
    
    @classmethod
    def total_persons(cls):
        return cls.count
    
    @classmethod
    def from_string(cls, person_string):  # Alternative constructor
        """Создаём Person из строки 'Name Age'"""
        name, age = person_string.split()
        # Вызываем инициализацию через класс
        obj = cls.__new__(cls)
        obj.name = name
        obj.age = int(age)
        return obj

p1 = Person("Alice")
p2 = Person("Bob")
print(Person.total_persons())  # 2

# Alternative constructor
p3 = Person.from_string("Charlie 30")
print(p3.name)  # "Charlie"
print(p3.age)   # 30

Практический пример — работа с разными форматами:

from datetime import datetime
import json

class Date:
    def __init__(self, day, month, year):
        self.day = day
        self.month = month
        self.year = year
    
    @classmethod
    def today(cls):
        """Создаём Date из сегодняшней даты"""
        now = datetime.now()
        return cls(now.day, now.month, now.year)
    
    @classmethod
    def from_string(cls, date_string):
        """Создаём из строки '2024-03-22'"""
        day, month, year = date_string.split('-')
        return cls(int(day), int(month), int(year))
    
    @classmethod
    def from_json(cls, json_string):
        """Создаём из JSON"""
        data = json.loads(json_string)
        return cls(data['day'], data['month'], data['year'])
    
    def __repr__(self):
        return f"Date({self.day}/{self.month}/{self.year})"

# Разные способы создания
d1 = Date.today()
d2 = Date.from_string('22-03-2024')
d3 = Date.from_json('{"day": 22, "month": 3, "year": 2024}')

4. Статический метод (Static Method)

Что это:

  • Не получает ни self, ни cls
  • Не может менять состояние инстанса или класса
  • Это просто функция в пространстве имён класса
  • Используется для утилит, не связанных с состоянием
import math

class Calculator:
    @staticmethod
    def add(a, b):
        return a + b
    
    @staticmethod
    def is_prime(n):
        if n < 2:
            return False
        for i in range(2, int(math.sqrt(n)) + 1):
            if n % i == 0:
                return False
        return True
    
    @staticmethod
    def format_currency(amount, currency="USD"):
        return f"{currency} {amount:.2f}"

# Вызов через класс или инстанс (неважно)
print(Calculator.add(5, 3))           # 8
print(Calculator.is_prime(17))        # True
print(Calculator.format_currency(123.456))  # USD 123.46

calc = Calculator()
print(calc.add(10, 20))               # 30 (работает с инстансом)

5. Сравнение трёх типов методов

class Example:
    class_var = "Класс"
    
    def __init__(self, instance_var):
        self.instance_var = instance_var
    
    # 1. ИНСТАНС МЕТОД
    def instance_method(self):
        print(f"self: {self}")
        print(f"instance_var: {self.instance_var}")
        print(f"class_var: {self.class_var}")  # Может читать
        self.instance_var = "изменено"  # Может менять инстанс
        # self.__class__.class_var = "новое"  # Может менять класс
    
    # 2. МЕТОД КЛАССА
    @classmethod
    def class_method(cls):
        print(f"cls: {cls}")
        print(f"class_var: {cls.class_var}")  # Может читать
        cls.class_var = "новое значение"  # Может менять класс
        # cls().instance_var  # Может создать инстанс и читать
    
    # 3. СТАТИЧЕСКИЙ МЕТОД
    @staticmethod
    def static_method():
        print("No self, no cls")
        # Ничего не может менять
        # return Example.class_var  # Может читать через имя класса

obj = Example("инстанс")
obj.instance_method()   # Вызов через инстанс
Example.class_method()  # Вызов через класс
Example.static_method() # Вызов через класс

print(Example.class_var)  # "новое значение" (изменился в class_method)

6. Когда что использовать

Инстанс метод (@это по умолчанию):

class BankAccount:
    def __init__(self, owner, balance):
        self.owner = owner
        self.balance = balance
    
    def deposit(self, amount):  # Инстанс метод
        self.balance += amount
        return f"Пополнено на {amount}"
    
    def withdraw(self, amount):  # Инстанс метод
        if amount <= self.balance:
            self.balance -= amount
            return f"Снято {amount}"
        return "Недостаточно средств"

Метод класса (для shared логики):

class BankAccount:
    total_accounts = 0  # Считаем все счёта
    
    def __init__(self, owner, balance):
        self.owner = owner
        self.balance = balance
        BankAccount.total_accounts += 1
    
    @classmethod
    def get_total_accounts(cls):
        return cls.total_accounts
    
    @classmethod
    def from_legacy_format(cls, legacy_data):
        # Конвертируем из старого формата
        owner = legacy_data['user_name']
        balance = float(legacy_data['amount'])
        return cls(owner, balance)

Статический метод (утилиты):

class StringUtils:
    @staticmethod
    def is_email(email):
        return '@' in email and '.' in email
    
    @staticmethod
    def reverse_string(s):
        return s[::-1]
    
    @staticmethod
    def count_vowels(text):
        return sum(1 for char in text.lower() if char in 'aeiou')

print(StringUtils.is_email("test@example.com"))  # True
print(StringUtils.reverse_string("Hello"))       # "olleH"

7. Таблица сравнения

ПризнакИнстанс методМетод классаСтатический метод
Первый параметрselfclsничего
Декораторнет (по умолчанию)@classmethod@staticmethod
Доступ к инстансу✓ Полный✗ Нет✗ Нет
Доступ к классу✓ Через self.class✓ Полный✗ Только через имя
Может менять инстанс
Может менять класс
Вызовobj.method()Class.method()Class.method()
Когда использоватьРабота с данными объектаЛогика класса, constructorsУтилиты, helper функции

Итоги

  • Инстанс метод — работает с данными конкретного объекта (self)
  • Метод класса — работает с данными класса и может быть alternative constructor (cls)
  • Статический метод — просто функция в пространстве имён класса (@staticmethod)
  • По умолчанию пиши инстанс методы
  • Используй @classmethod для альтернативных конструкторов и логики на уровне класса
  • Используй @staticmethod для вспомогательных функций, не связанных с состоянием
В чем разница между методом и инстансом класса? | PrepBro