Python · Stored Types

Stored Types

1.0.0-rc.1 · c4d34add

Values are int, float, bool, str and bytes, deep-copied into memory the library owns, so a stored value outlives the object it came from. str and bytes stay distinct, and bool round-trips as bool rather than as 1.

A container may instead hold arbitrary objects, which it stores by reference rather than by copy:

documents = st.SortedMap(key=str, value='object')
documents['doc'] = {'nested': [1, 2]}   # the very same object comes back out

The mode is named rather than inferred, because it is what the scalar guarantee rests on. In the default scalar mode nothing stored can touch a reference count, so the interpreter lock is released around every store; in object mode it is held, and the container is correspondingly slower.

Keys are typed and homogeneous. A container names its key layout at construction and refuses every other type:

st.SortedMap(key=int)      # signed 64-bit
st.SortedMap(key='uint')   # unsigned 64-bit, the only way to ask, since Python has no unsigned type
st.SortedMap(key=str)      # UTF-8, ordered bytewise
st.SortedMap(key=bytes)    # opaque, never decoded

That is what lets every comparison skip type dispatch: the ordering function is chosen once, at construction, rather than re-derived from a tag on each of the millions of comparisons a tree makes.

float and bool are values but never keys. A float key would make ordering depend on a total order over NaN, and bool is a subclass of int in Python, so accepting it would silently alias two key spaces:

m = st.SortedMap(key=int)
m[1] = 'one'      # fine
m[1.0] = 'one'    # TypeError: float is not a valid key
m[True] = 'one'   # TypeError: bool is not a valid key

This is the one place the library is deliberately stricter than dict, which treats 1, 1.0 and True as one key.