← Назад к вопросам
В чем разница между атрибутом класса и объекта?
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__
Правило: Если несколько объектов должны иметь разные значения - атрибут объекта. Если значение общее для всех - атрибут класса.