Ответ
@classmethod — это декоратор в Python, который определяет метод класса. Первым аргументом такого метода является сам класс (по соглашению cls), а не экземпляр (self). Это позволяет работать с атрибутами уровня класса и создавать альтернативные конструкторы, что полезно для организации кода в утилитах и скриптах автоматизации.
Основные отличия от обычного метода (self) и статического метода (@staticmethod):
| Метод | Первый аргумент | Может обращаться к атрибутам класса? | Может обращаться к атрибутам экземпляра? |
|---|---|---|---|
| Обычный | self (экземпляр) |
Да (через self.__class__) |
Да |
@classmethod |
cls (класс) |
Да | Нет (без экземпляра) |
@staticmethod |
Нет | Нет | Нет |
Практические примеры использования в DevOps-скриптах:
-
Альтернативный конструктор для создания объектов из конфигурации (YAML/JSON):
class ServerConfig: def __init__(self, host, port, user): self.host = host self.port = port self.user = user @classmethod def from_yaml(cls, filepath): """Создает экземпляр ServerConfig из YAML-файла.""" import yaml with open(filepath, 'r') as f: data = yaml.safe_load(f) # Здесь может быть валидация данных return cls(data['host'], data['port'], data['user']) # Использование config = ServerConfig.from_yaml('server_config.yaml') print(f"Подключаемся к {config.host}:{config.port}") -
Управление общим состоянием или кэшем на уровне класса:
class DeploymentRegistry: _deployed_services = set() # Атрибут класса, общий для всех экземпляров def __init__(self, service_name): self.service_name = service_name def deploy(self): # ... логика деплоя ... self.__class__.add_to_registry(self.service_name) @classmethod def add_to_registry(cls, service): cls._deployed_services.add(service) @classmethod def get_all_deployed(cls): return list(cls._deployed_services) # В разных частях скрипта deploy1 = DeploymentRegistry('api-service') deploy2 = DeploymentRegistry('frontend-service') deploy1.deploy() deploy2.deploy() print(DeploymentRegistry.get_all_deployed()) # ['api-service', 'frontend-service'] -
Фабричный метод для создания объектов в зависимости от окружения:
class CloudStorage: def __init__(self, bucket): self.bucket = bucket def upload(self, file): raise NotImplementedError @classmethod def for_environment(cls, env): """Возвращает правильную реализацию хранилища для окружения.""" if env == "aws": return S3Storage() elif env == "gcp": return GCSStorage() else: return LocalStorage() class S3Storage(CloudStorage): def upload(self, file): print(f"Uploading {file} to AWS S3 bucket {self.bucket}") # Использование в скрипте деплоя storage = CloudStorage.for_environment(os.getenv('CLOUD_PROVIDER', 'aws')) storage.upload('backup.tar.gz')
Использование @classmethod делает код скриптов более модульным, тестируемым и удобным для расширения.
Видео-ответы
▶
▶
▶
▶
▶
▶