Skip to content

Latest commit

 

History

History
78 lines (56 loc) · 2.33 KB

File metadata and controls

78 lines (56 loc) · 2.33 KB

📦 Smart containers

Drop-in replacements for dict and list that add type casting, uniqueness and slicing — while staying ordinary dict/list subclasses you can pass anywhere.

CastedDict — cast keys and values on the way in

Give it a key cast and a value cast (either may be None to skip). Every assignment — including update and construction — is cast eagerly, so what you store is already the right type:

from python_utils import containers

d = containers.CastedDict(int, int)
d['3'] = '4'
d.update({'5': '6'})
d                       # {3: 4, 5: 6}

Use the subscription syntax to keep type checkers happy:

d: containers.CastedDict[int, int] = containers.CastedDict(int, int)

LazyCastedDict — cast values only when read

Same idea, but values are stored raw and cast on access. Handy when casting is expensive and you only read a subset of the keys. Note that values are not cached, so the cast runs on every read:

from python_utils import containers

d = containers.LazyCastedDict(int, int)
d['3'] = '4'
d.update({'5': '6'})

d                       # {3: '4', 5: '6'}   <- values still raw
d[3]                    # 4                   <- cast on access
list(d.values())        # [4, 6]

UniqueList — a list that rejects duplicates

By default duplicates are silently ignored; set on_duplicate='raise' to turn them into errors instead. Uniqueness is enforced across append, insert, extend and item assignment, backed by an internal set for O(1) membership tests:

from python_utils import containers

u = containers.UniqueList(1, 2, 3)
u.append(2)             # ignored
u                       # [1, 2, 3]

strict = containers.UniqueList(1, 2, 3, on_duplicate='raise')
strict.append(2)        # ValueError: Duplicate value: 2

SliceableDeque — a deque you can slice

A collections.deque keeps fast appends and pops at both ends but doesn't support slicing. SliceableDeque adds it, plus friendly equality against lists, tuples and sets:

from python_utils import containers

s = containers.SliceableDeque([1, 2, 3, 4, 5])
s[1:4]                  # SliceableDeque([2, 3, 4])
s[::-1]                 # SliceableDeque([5, 4, 3, 2, 1])
s == [1, 2, 3, 4, 5]    # True

See the {doc}API reference <../python_utils> for every method and overload.