"""
Utils related to classes.
"""
from nnsa.utils.dictionaries import nested_update, itemize_items
from nnsa.utils.objects import basic_repr
__all__ = [
'ClassWithParameters',
'Parameters',
]
[docs]class ClassWithParameters(object):
"""
Base class for a class that has parameters.
Args:
**kwargs (optional): optional keyword arguments for overruling default parameters. For a description of the
possible parameters, see the default_parameters() method.
"""
def __init__(self, **kwargs):
# Initialize Parameters object.
parameters = Parameters()
# Add default parameters to Parameters object (be compatible with default_parameters() methods that return
# dict).
parameters.add(self.default_parameters())
# Update default parameters with keyword arguments.
parameters.update(kwargs)
self.parameters = parameters
def __repr__(self):
return basic_repr(self)
[docs] @staticmethod
def default_parameters():
"""
Return the default parameters as a dictionary.
Returns:
(dict or Parameters): a default set of parameters for the object.
"""
raise NotImplementedError
[docs]class Parameters(dict):
"""
Class for collecting parameters.
Inherits from dict, so functionality is mostly identical to dict.
Customized/added methods of Parameters are:
__repr__: returns a more readable representation of the set.
add: mimics the update method of dict to add new entries.
update: only accepts existing keys.
Examples:
>>> d = {'a': 1, 'b': {'c': {'d': 1}, 'e': 1}}
>>> p = Parameters(**d)
>>> print(p)
Parameters object with:
a: 1
b: {'c': {'d': 1}, 'e': 1}
>>> p.update({'b': {'e': 2}})
>>> print(p)
Parameters object with:
a: 1
b: {'c': {'d': 1}, 'e': 2}
>>> p.update({'c': 2})
Traceback (most recent call last):
...
KeyError: "'c' not in collection with keys ['a', 'b']."
>>> p['c'] = 3
>>> p.add({'x': 3, 'y': {'z': 3}})
>>> dict(p)
{'a': 1, 'b': {'c': {'d': 1}, 'e': 2}, 'c': 3, 'x': 3, 'y': {'z': 3}}
"""
def __repr__(self):
return '{} object with:\n{}'.format(self.__class__.__name__, itemize_items(self.items()))
[docs] def add(self, other=None, **kwargs):
"""
Add or update keys, value pairs in the Parameters set (in place).
Args:
other (dict or iterable, optional): dictionary or iterable of key, value pairs to add to the Parameters set.
**kwargs (optional): keyword arguments to add (in which the keyword is the key).
"""
if other is not None:
super().update(other)
if kwargs:
super().update(**kwargs)
[docs] def update(self, other=None, **kwargs):
"""
Update key, value pairs in the Parameter set, accepting only existing keys.
Updates nested dictionaries/Parameters objects up to arbitrary levels. In the deeper levels, non-existing keys
are accepted if they are from an ordinary dict. In contrast, updating a non-existent key in a deeper Parameters
object will raise an error.
Args:
other (dict or iterable, optional): dictionary or iterable of key, value pairs with which to update.
**kwargs (optional): keyword arguments with which to update (in which the keyword is the key).
Raises:
KeyError: if key to update not in Parameter set.
"""
nested_update(self, other=other, accept_new_key='parameters_mode', **kwargs)