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

«В чем разница между атрибутом класса и атрибутом экземпляра класса в Python?» — вопрос из категории Скриптинг и автоматизация, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В контексте DevOps и автоматизации (например, для создания утилит или модулей управления инфраструктурой) понимание этой разницы критично.

Атрибут класса принадлежит самому классу и является общим для всех его экземпляров. Атрибут экземпляра принадлежит конкретному объекту (экземпляру) и уникален для него.

Пример: Модель сервера в скрипте инвентаризации

class Server:
    # Атрибут класса - общий для всех серверов
    platform = "Linux"
    config_manager = "Ansible"

    def __init__(self, hostname, ip_address):
        # Атрибуты экземпляра - уникальны для каждого сервера
        self.hostname = hostname
        self.ip = ip_address
        self.services = []  # Инициализируется для каждого экземпляра отдельно

# Создаем экземпляры
web_srv = Server("web01", "192.168.1.10")
db_srv = Server("db01", "192.168.1.20")

# Доступ к атрибуту класса (одинаковый для всех)
print(web_srv.platform)      # Вывод: Linux
print(db_srv.config_manager) # Вывод: Ansible

# Доступ к атрибутам экземпляра (разные)
print(web_srv.hostname)      # Вывод: web01
print(db_srv.ip)             # Вывод: 192.168.1.20

# Изменение атрибута класса влияет на все экземпляры
Server.platform = "Unix"
print(web_srv.platform)      # Вывод: Unix (изменилось!)
print(db_srv.platform)       # Вывод: Unix (изменилось!)

# Изменение атрибута экземпляра влияет только на него
web_srv.services.append("nginx")
db_srv.services.append("postgresql")
print(web_srv.services)      # Вывод: ['nginx']
print(db_srv.services)       # Вывод: ['postgresql']

Зачем это важно в DevOps/автоматизации?

  • Атрибуты класса отлично подходят для хранения констант, общих настроек или shared state (например, кеша соединений, логгера) для всех объектов этого типа.
  • Атрибуты экземпляра используются для хранения уникальных данных объекта (имя хоста, IP, состояние, метрики).

Осторожно: Изменяемые атрибуты класса (например, список default_ports = []) могут привести к неожиданному поведению, если экземпляры будут его изменять. Для изменяемых значений по умолчанию лучше использовать None в атрибуте класса и инициализировать список в __init__.