slicing a bsddb table, eg. for rec in bsddb["AArdvark":"zebra"]: print rec

Bengt Richter bokr at oz.net
Sun Jun 26 16:49:45 EDT 2005


On Sun, 12 Jun 2005 16:49:57 -0500, Skip Montanaro <skip at pobox.com> wrote:

>
>    Neville> # I was expecting a slice of an index file to yield a
>    Neville> # generator so not all the records need to be read from disk....
>
>Slicing is a feature of sequence types, not mapping types.
>
>    >>> import string
>    >>> d = dict(zip(string.lowercase, string.uppercase))
>    >>> d
>    {'a': 'A', 'c': 'C', 'b': 'B', 'e': 'E', 'd': 'D', ...}
>    >>> d["a":"z"]
>    Traceback (most recent call last):
>      File "<stdin>", line 1, in ?
>    TypeError: unhashable type
>    >>> import UserDict
>    >>> d2 = UserDict.UserDict(d)
>    >>> d2
>    {'a': 'A', 'c': 'C', 'b': 'B', 'e': 'E', 'd': 'D', ...}
>    >>> d2["a":"z"]
>    Traceback (most recent call last):
>      File "<stdin>", line 1, in ?
>      File "/Users/skip/local/lib/python2.5/UserDict.py", line 17, in __getitem__
>        def __getitem__(self, key): return self.data[key]
>    TypeError: unhashable type
>
>The unhashable type it's referring to is the slice object generated by the
>"a":"z" notation:
>
>    >>> hash(slice("a", "z"))
>    Traceback (most recent call last):
>      File "<stdin>", line 1, in ?
>    TypeError: unhashable type
>
>If you look at help on the slice type, you'll see that it takes three args:
>
>    class slice(object)
>     |  slice([start,] stop[, step])
>     |  
>     | Create a slice object.  This is used for extended slicing
>     | (e.g. a[0:10:2]).
>     |  
>
>Step sizes really only make sense for sequence indices.
>
Yes, but if you have an implicit sort assumption for your keys, you can treat them
as a sequence, and slice out the keys of interest and get their values, e.g.,
(no guarantees, not tested beyond what you see, that I just hacked here ;-)

 >>> class SliceDict(dict):
 ...     def __getitem__(self, i):
 ...         if type(i) is slice:
 ...             keys = sorted(self.keys())
 ...             start = i.start; stop = i.stop
 ...             try: start = keys.index(start)
 ...             except ValueError:
 ...                 if start is not None: raise KeyError, start
 ...             try: stop  = keys.index(stop )
 ...             except ValueError:
 ...                 if stop is not None: raise KeyError, stop
 ...             return [dict.__getitem__(self, k) for k in keys[start:stop]]
 ...         else:
 ...             return dict.__getitem__(self, i)
 ...
 >>> sd = SliceDict(a=1,b=2,z=26,k=11)
 >>> sd['b':'z']
 [2, 11]
 >>> sd['b':]
 [2, 11, 26]
 >>> sd[:'z']
 [1, 2, 11]
 >>> sd['b':'z']
 [2, 11]
 >>> sd['b']
 2
 >>> sorted(sd.items())
 [('a', 1), ('b', 2), ('k', 11), ('z', 26)]
 >>> sd['x':'k']
 Traceback (most recent call last):
   File "<stdin>", line 1, in ?
   File "<stdin>", line 8, in __getitem__
 KeyError: 'x'
 >>> sd['x']
 Traceback (most recent call last):
   File "<stdin>", line 1, in ?
   File "<stdin>", line 14, in __getitem__
 KeyError: 'x'

Hm, None as an actual key might be a little problematical though ;-)

I would think this could be a handy way to get data base records that were selected
from a range of sorted keys using sql and loading a dict like the above.

Regards,
Bengt Richter



More information about the Python-list mailing list