#!/usr/bin/env python # coding: utf-8 # In[1]: from datashape import dshape, discover from datashape.dispatch import dispatch from odo import convert, append, odo # In[2]: class TypedList(list): """A list with type checked values. Paramaters ---------- dtype : dshape The type of the valus in the list. data : iterable of dtype, optional The values to initialize the list with. """ def __init__(self, dtype, data=None): super().__init__(()) self.dtype = dshape(dtype).measure if data: self.extend(data) def _checktype(self, value): if discover(value) != self.dtype: raise TypeError( "value '%s' is of type '%s', not type '%s'" % ( value, discover(value).measure, self.dtype, ), ) def __setitem__(self, idx, value): self._checktype(value) super().__setitem__(idx, value) def append(self, value): self._checktype(value) super().append(value) def extend(self, vs): for v in vs: self.append(v) def __repr__(self): return '%s::%s' % (super().__repr__(), self.dtype) # In[ ]: # In[3]: tl = TypedList('int64', [1, 2, 3]) tl # In[4]: tl.append('a') # In[5]: tl.append(3) tl # In[6]: @dispatch(TypedList) def discover(tl): return len(tl) * tl.dtype # In[7]: discover(tl) # In[8]: @convert.register(TypedList, list) def list_to_typed_list(ds, dshape=None, **kwargs): if dshape is None: dshape = discover(ds).measure.measure return TypedList(dshape, ds) @convert.register(list, TypedList) def list_to_typed_list(ds, **kwargs): return list(ds) # In[9]: odo(tl, list) # In[10]: odo(tl, set) # In[11]: odo(tl, tuple) # In[12]: import numpy as np odo(tl, np.ndarray) # In[13]: odo(TypedList('float64', [1.2, 1.3, 1.4]), np.ndarray) # In[14]: odo([1, 2, 3], TypedList, dtype='int64') # In[15]: odo(np.array([1, 2, 3]), TypedList('int64')) # In[17]: @append.register(list, TypedList) def append_list_to_typed_list(ds, tl, **kwargs): tl.extend(ds) # In[18]: odo([1, 2, 3], tl) # In[19]: tl # In[ ]: