0

I am trying to define a typed dictionary in Python. I have written the following snippet but I wonder if there is a better way to achieve the same goal. I am using defaultdict but feel free to change that to dict for the base if you want.

from collections import defaultdict

class typed_dict(defaultdict):

    def __init__(self, key_type, val_type, *args, **kwargs):
        self.key_type = key_type
        if type(val_type) == type(lambda: 1):
            self.val_type = type(val_type())
        else:
            self.val_type = val_type
        super(typed_dict, self).__init__(val_type, *args, **kwargs)

    def __getitem__(self, k):
        try:
            assert type(k) == self.key_type
            return super(typed_dict, self).__getitem__(k)
        except AssertionError:
            print('key mismatch, got {}, must be {}'.format(type(k), self.key_type))

    def __setitem__(self, k, v):
        try:
            assert type(k) == self.key_type
            assert type(v) == self.val_type
            super(typed_dict, self).__setitem__(k, v)
        except AssertionError:
            print('key or value mismatch, got {}: {}, \
 must be {}: {}'.format(type(k), type(v), self.key_type, self.val_type))



d = typed_dict(int, str)
d[1]
d[2] = "two"
d["one"]
d["three"] = 3
d[3] = 3
print(d)

d = typed_dict(int, lambda: '')
d[1]
d[2] = "two"
d["one"]
d["three"] = 3
d[3] = 3
print(d)

import numpy as np
d = typed_dict(int, lambda: np.zeros(2))
d[1]
d[2] = "two"
d[3] = np.array([1,2,3])
print(d)
s.yadegari
  • 603
  • 6
  • 9
  • 2
    Idiomatic Python does **not** do type checking at runtime for every operation. See [Python >=3.5: Checking type annotation at runtime](//stackoverflow.com/q/43646823) for some of the motivations why not. – Martijn Pieters Jan 03 '19 at 16:46
  • `type(lambda: 1)` should probably be `types.FunctionType`. Or even `collections.abc.Callable` – Patrick Haugh Jan 03 '19 at 16:47
  • Nor is what you created here a form of type *hinting*. You are using concrete type checking here. – Martijn Pieters Jan 03 '19 at 16:47
  • 1
    Next, when comparing types, it is usually done based on identity. `type(...) is type(...)` if it is done at all. You should probably use `isinstance()` tests instead. See [What's the canonical way to check for type in Python?](//stackoverflow.com/q/152580) – Martijn Pieters Jan 03 '19 at 16:48
  • 1
    As such, Pythonic code would use type hinting (actual type hints) to have a tool like mypy check the types statically, then have your code run without the burden of checking every single key and value. – Martijn Pieters Jan 03 '19 at 16:53

0 Answers0