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

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

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

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

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

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

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

Атрибут класса (class attribute) - это переменная, определенная в классе и разделяемая всеми экземплярами. Атрибут объекта (instance attribute) - это переменная, определенная для конкретного экземпляра и уникальна для каждого объекта.

Атрибут класса

class Dog:
    species = 'Canis familiaris'  # Атрибут класса
    
    def __init__(self, name):
        self.name = name  # Атрибут объекта

# Атрибут класса разделяется между всеми экземплярами
dog1 = Dog('Rex')
dog2 = Dog('Bud')

print(dog1.species)  # 'Canis familiaris'
print(dog2.species)  # 'Canis familiaris'
print(Dog.species)   # 'Canis familiaris'

# Это один и тот же объект
print(Dog.species is dog1.species)  # True
print(dog1.species is dog2.species)  # True

Атрибут объекта

class Dog:
    def __init__(self, name):
        self.name = name  # Атрибут объекта

dog1 = Dog('Rex')
dog2 = Dog('Bud')

print(dog1.name)  # 'Rex'
print(dog2.name)  # 'Bud'

# Разные объекты
print(dog1.name is dog2.name)  # False

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

class Dog:
    tricks = []  # ❌ Опасно! Список разделяется
    
    def __init__(self, name):
        self.name = name
    
    def add_trick(self, trick):
        self.tricks.append(trick)  # Модифицирует shared список!

dog1 = Dog('Rex')
dog2 = Dog('Bud')

dog1.add_trick('Sit')
dog1.add_trick('Stay')

print(dog1.tricks)  # ['Sit', 'Stay']
print(dog2.tricks)  # ['Sit', 'Stay'] - ??!

# Проблема: оба собаки имеют одни и те же трюки!

Правильный способ

class Dog:
    tricks = []  # Атрибут класса (пустой для начала)
    
    def __init__(self, name):
        self.name = name
        self.tricks = []  # Атрибут объекта - свой список
    
    def add_trick(self, trick):
        self.tricks.append(trick)

dog1 = Dog('Rex')
dog2 = Dog('Bud')

dog1.add_trick('Sit')
dog1.add_trick('Stay')

print(dog1.tricks)  # ['Sit', 'Stay']
print(dog2.tricks)  # [] - OK, свой список

Порядок поиска атрибутов

# Python ищет в порядке:
# 1. Атрибут объекта (__dict__)
# 2. Атрибут класса
# 3. Атрибут суперкласса

class Dog:
    species = 'Canis familiaris'  # Атрибут класса

dog = Dog()
dog.species = 'Собака'  # Создаем атрибут объекта

print(dog.species)      # 'Собака' - из объекта
print(Dog.species)      # 'Canis familiaris' - из класса
print(dog.__dict__)     # {'species': 'Собака'}
print(Dog.__dict__)     # {'species': 'Canis familiaris', ...}

Изменение атрибута класса

class Dog:
    count = 0  # Счетчик всех собак
    
    def __init__(self, name):
        self.name = name
        Dog.count += 1  # Изменяем атрибут класса
    
    @classmethod
    def get_count(cls):
        return cls.count

dog1 = Dog('Rex')
dog2 = Dog('Bud')
dog3 = Dog('Max')

print(Dog.get_count())  # 3
print(Dog.count)        # 3

Практический пример: конфигурация

class Config:
    # Атрибуты класса - конфигурация
    DEBUG = True
    DATABASE_URL = 'postgresql://localhost'
    TIMEOUT = 30

config1 = Config()
config2 = Config()

# Все экземпляры разделяют одну конфигурацию
print(config1.DEBUG)  # True
print(config2.DEBUG)  # True

# Изменение через класс
Config.DEBUG = False
print(config1.DEBUG)  # False
print(config2.DEBUG)  # False

Пример: счетчик экземпляров

class User:
    count = 0  # Атрибут класса - счетчик
    
    def __init__(self, name):
        self.name = name  # Атрибут объекта
        User.count += 1   # Увеличиваем счетчик класса
    
    def __del__(self):
        User.count -= 1  # Уменьшаем при удалении
    
    @classmethod
    def get_total_users(cls):
        return cls.count

user1 = User('Alice')
user2 = User('Bob')
print(User.get_total_users())  # 2

del user1
print(User.get_total_users())  # 1

Проверка атрибутов

class Dog:
    species = 'Canis familiaris'
    
    def __init__(self, name):
        self.name = name

dog = Dog('Rex')

# Есть ли атрибут в объекте?
print(hasattr(dog, 'name'))      # True
print(hasattr(dog, 'species'))   # True (из класса)

# Какие атрибуты есть?
print(dog.__dict__)      # {'name': 'Rex'} - только объекта
print(Dog.__dict__.keys())  # 'species', '__init__', ...

# Откуда атрибут?
if 'name' in dog.__dict__:
    print("Атрибут объекта")
else:
    print("Атрибут класса")

Статические методы vs методы класса

class Dog:
    species = 'Canis familiaris'
    count = 0
    
    @staticmethod
    def is_mammal():
        # Не имеет доступа к self или cls
        return True
    
    @classmethod
    def get_species(cls):
        # Имеет доступ к атрибутам класса
        return cls.species
    
    def get_name(self):
        # Имеет доступ к атрибутам объекта
        return self.name

print(Dog.is_mammal())      # True - staticmethod
print(Dog.get_species())    # 'Canis familiaris' - classmethod
dog = Dog()
print(dog.get_name())       # Нужен объект

Вывод

Атрибут класса:

  • Разделяется всеми экземплярами
  • Используй для конфигурации, констант, счетчиков
  • Изменяй через класс: ClassName.attribute = value

Атрибут объекта:

  • Уникален для каждого экземпляра
  • Используй для данных конкретного объекта
  • Обычно создаешь в __init__

Правило: Если несколько объектов должны иметь разные значения - атрибут объекта. Если значение общее для всех - атрибут класса.

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