@@ -164,17 +164,38 @@ def __init__(self, attributes, class_vars=None, metas=None, source=None):
164
164
if not all (var .is_primitive () for var in self ._variables ):
165
165
raise TypeError ("variables must be primitive" )
166
166
167
- self ._indices = dict (chain .from_iterable (
168
- ((var , idx ), (var .name , idx ), (idx , idx ))
169
- for idx , var in enumerate (self ._variables )))
170
- self ._indices .update (chain .from_iterable (
171
- ((var , - 1 - idx ), (var .name , - 1 - idx ), (- 1 - idx , - 1 - idx ))
172
- for idx , var in enumerate (self .metas )))
167
+ self ._indices = None
173
168
174
169
self .anonymous = False
175
170
176
171
self ._hash = None # cache for __hash__()
177
172
173
+ def _ensure_indices (self ):
174
+ if self ._indices is None :
175
+ self ._indices = dict (chain .from_iterable (
176
+ ((var , idx ), (var .name , idx ), (idx , idx ))
177
+ for idx , var in enumerate (self ._variables )))
178
+ self ._indices .update (chain .from_iterable (
179
+ ((var , - 1 - idx ), (var .name , - 1 - idx ), (- 1 - idx , - 1 - idx ))
180
+ for idx , var in enumerate (self .metas )))
181
+
182
+ def __setstate__ (self , state ):
183
+ self .__dict__ .update (state )
184
+ self ._variables = self .attributes + self .class_vars
185
+ self ._indices = None
186
+ self ._hash = None
187
+
188
+ def __getstate__ (self ):
189
+ # Do not pickle dictionaries because unpickling dictionaries that
190
+ # include objects that redefine __hash__ as keys is sometimes problematic
191
+ # (when said objects do not have __dict__ filled yet in but are used as
192
+ # keys in a restored dictionary).
193
+ state = self .__dict__ .copy ()
194
+ del state ["_variables" ]
195
+ del state ["_indices" ]
196
+ del state ["_hash" ]
197
+ return state
198
+
178
199
# noinspection PyPep8Naming
179
200
@classmethod
180
201
def from_numpy (cls , X , Y = None , metas = None ):
@@ -289,7 +310,7 @@ def __getitem__(self, idx):
289
310
"""
290
311
if isinstance (idx , slice ):
291
312
return self ._variables [idx ]
292
-
313
+ self . _ensure_indices ()
293
314
index = self ._indices .get (idx )
294
315
if index is None :
295
316
var = self ._get_equivalent (idx )
@@ -306,6 +327,7 @@ def __contains__(self, item):
306
327
Return `True` if the item (`str`, `int`, :class:`Variable`) is
307
328
in the domain.
308
329
"""
330
+ self ._ensure_indices ()
309
331
return item in self ._indices or self ._get_equivalent (item ) is not None
310
332
311
333
def __iter__ (self ):
@@ -334,7 +356,7 @@ def index(self, var):
334
356
Return the index of the given variable or meta attribute, represented
335
357
with an instance of :class:`Variable`, `int` or `str`.
336
358
"""
337
-
359
+ self . _ensure_indices ()
338
360
idx = self ._indices .get (var )
339
361
if idx is not None :
340
362
return idx
0 commit comments