1

I'm thinking how can we implement a InsertOnlyDict, which have the property that, if a key already exists, it can't be set to new value.

One way to implement it is to write something like:

class InsertOnlyDict(dict):
  def __setitem__(self, key, value):
    if key in self:
      raise ....
    super(InsertOnlyDict, self).__setitem__(key, value)

The method above has the problem that, if caller uses dict.__setitem__(x, k, v), it can still update this.

The second way to implement this is to write,

class InsertOnlyDict(object):
  __slots__ = ('_internal',)
  def __init__(self, *args, **kwargs):
    self._internal = dict(*args, **kwargs):

  def __setitem__(self, key, value):
    if key in self._internal:
      raise....
    self._internal[key] = value

The most concern of this approach is that, this InsertOnlyDict is no longer a dict and can hence fails checks like isinstance(x, dict).

Is there any way to get around it? e.g. making a class not really using parent's class while still getting through checks like isinstance(x, dict)?

What do you think about these approaches?

martineau
  • 119,623
  • 25
  • 170
  • 301
Nan Hua
  • 31
  • 4
  • 2
    No, if you want to use a dict, you have to accept that dicts are allowed to do things you don't want them to. In this case testing for `isinstance(x, dict)` would be incorrect, since if `x` is an instance of a dict, then dict methods would work on it – Adam Smith Jun 05 '19 at 01:24
  • take a look of this [answer](https://stackoverflow.com/questions/2060972/subclassing-python-dictionary-to-override-setitem) – Valen Jun 05 '19 at 01:25
  • 3
    You mention "The method above has the problem that, if caller uses dict.setitem(x, k, v), it can still update this". But that's Python's philosophy. You don't have to code a solution that blocks a programmer from purposedly achieve something. You've blocked involuntary re-assignments and I think that's just as far as you need to go... – Roberto Jun 05 '19 at 01:26
  • you have to implement `update()` and `setdefault()` too – Valen Jun 05 '19 at 01:28
  • I think it's _very_ unlikely anyone would use `dict.__setitem__(x, k, v)` on it (which actually would need to be something like `dict.__setitem__(iod_object, x, k, v)`) — so would do it that way. Likewise for the other methods that are going to also need to be overridden. – martineau Jun 05 '19 at 01:42

0 Answers0