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