_bunch.py 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. import warnings
  2. class Bunch(dict):
  3. """Container object exposing keys as attributes.
  4. Bunch objects are sometimes used as an output for functions and methods.
  5. They extend dictionaries by enabling values to be accessed by key,
  6. `bunch["value_key"]`, or by an attribute, `bunch.value_key`.
  7. Examples
  8. --------
  9. >>> from sklearn.utils import Bunch
  10. >>> b = Bunch(a=1, b=2)
  11. >>> b['b']
  12. 2
  13. >>> b.b
  14. 2
  15. >>> b.a = 3
  16. >>> b['a']
  17. 3
  18. >>> b.c = 6
  19. >>> b['c']
  20. 6
  21. """
  22. def __init__(self, **kwargs):
  23. super().__init__(kwargs)
  24. # Map from deprecated key to warning message
  25. self.__dict__["_deprecated_key_to_warnings"] = {}
  26. def __getitem__(self, key):
  27. if key in self.__dict__.get("_deprecated_key_to_warnings", {}):
  28. warnings.warn(
  29. self._deprecated_key_to_warnings[key],
  30. FutureWarning,
  31. )
  32. return super().__getitem__(key)
  33. def _set_deprecated(self, value, *, new_key, deprecated_key, warning_message):
  34. """Set key in dictionary to be deprecated with its warning message."""
  35. self.__dict__["_deprecated_key_to_warnings"][deprecated_key] = warning_message
  36. self[new_key] = self[deprecated_key] = value
  37. def __setattr__(self, key, value):
  38. self[key] = value
  39. def __dir__(self):
  40. return self.keys()
  41. def __getattr__(self, key):
  42. try:
  43. return self[key]
  44. except KeyError:
  45. raise AttributeError(key)
  46. def __setstate__(self, state):
  47. # Bunch pickles generated with scikit-learn 0.16.* have an non
  48. # empty __dict__. This causes a surprising behaviour when
  49. # loading these pickles scikit-learn 0.17: reading bunch.key
  50. # uses __dict__ but assigning to bunch.key use __setattr__ and
  51. # only changes bunch['key']. More details can be found at:
  52. # https://github.com/scikit-learn/scikit-learn/issues/6196.
  53. # Overriding __setstate__ to be a noop has the effect of
  54. # ignoring the pickled __dict__
  55. pass