class_docstr: Mixin that provides save and load functionalities.
code: def __save(self, dirname: str, ancestors: List[Any]):
      os.makedirs(dirname, exist_ok=True)
      ancestors.append(self)
      for attr in self.saved_attributes:
          assert hasattr(self, attr)
          attr_value = getattr(self, attr)
          if attr_value is None:
              continue
          if isinstance(attr_value, AttributeSavingMixin):
              assert not any(
                  attr_value is ancestor for ancestor in ancestors
              ), "Avoid an infinite loop"
              attr_value.__save(os.path.join(dirname, attr), ancestors)
          else:
              if isinstance(
                  attr_value,
                  (
                      torch.nn.parallel.DistributedDataParallel,
                      torch.nn.DataParallel,
                  ),
              ):
                  attr_value = attr_value.module
              torch.save(
                  attr_value.state_dict(),
                  os.path.join(dirname, "{}.pt".format(attr)),
              )
      ancestors.pop()
  
imports: import contextlib
  import os
  from abc import ABCMeta, abstractmethod, abstractproperty
  from typing import Any, List, Optional, Sequence, Tuple
  import torch
label_desc: Use image node_id 3 for calling the AttributeSavingMixin obj's underlying member method code with example usage: obj.__save(dirname, ancestors) without return types