Source code for NuRadioReco.utilities.metaclasses

import logging
logger = logging.getLogger('NuRadioReco.metaclasses')

[docs] class Singleton(type): """ Can be assigned to classes as a metaclass. By default, only one instance of a Singleton can exist at a time, as the ``__call__`` method is overwritten to return the existing instance if one exists. """ _instances = {} _args_kwargs = {} def __call__(cls, *args, **kwargs): """ Overwrites the __call__ method Checks if an instance of the class already exists and returns that instance instead of creating a new one, unless ``create_new=True`` is specified. Parameters ---------- create_new: bool (default: None) * If ``False``, this will always attempt to return an existing instance of the class. If the existing instance was created with different initial arguments, this raises an error. * If ``True``, a new instance will always be created, even if one already exists. * If ``None`` (default), try to return an existing instance only if the provided arguments match, otherwise return a new instance (implies ``create_new=True``). Notes ----- The `Singleton` metaclass is intended for classes that are expensive to initialize (e.g. because of a large amount of I/O, such as loading an antenna model from disk). """ create_new = kwargs.pop('create_new', None) create_new = ( create_new or cls not in Singleton._instances or create_new is None and (args, kwargs) != Singleton._args_kwargs[cls] ) if create_new: logger.debug(f'Creating new instance of {cls}...') Singleton._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) Singleton._args_kwargs[cls] = (args, kwargs) elif (args, kwargs) != Singleton._args_kwargs[cls]: msg = ( f'Singleton {cls} was already initialized with different arguments. ' 'To create a new instance with different initial values, include ' '`create_new=True` in the class initialization call.' ) raise ValueError(msg) return Singleton._instances[cls]