no-clobber dicts?

Discussion in 'Python' started by kj, Aug 3, 2009.

  1. kj

    kj Guest

    I use the term "no-clobber dict" to refer to a dictionary D with
    the especial property that if K is in D, then

    D[K] = V

    will raise an exception unless V == D[K]. In other words, D[K]
    can be set if K doesn't exist already among D's keys, or if the
    assigned value is equal to the current value of D[K]. All other
    assignments to D[K] trigger an exception.

    The idea here is to detect inconsistencies in the data.

    This is a data structure I often need. Before I re-invent the
    wheel, I thought I'd ask: is it already available?

    TIA!

    kynn
     
    kj, Aug 3, 2009
    #1
    1. Advertising

  2. kj

    r Guest

    On Aug 3, 4:07 pm, kj <> wrote:
    > I use the term "no-clobber dict" to refer to a dictionary D with
    > the especial property that if K is in D, then
    >
    >   D[K] = V
    >
    > will raise an exception unless V == D[K].  In other words, D[K]
    > can be set if K doesn't exist already among D's keys, or if the
    > assigned value is equal to the current value of D[K].  All other
    > assignments to D[K] trigger an exception.
    >
    > The idea here is to detect inconsistencies in the data.
    >
    > This is a data structure I often need.  Before I re-invent the
    > wheel, I thought I'd ask: is it already available?
    >
    > TIA!
    >
    > kynn


    Not sure if something like this already exists, but it would be
    trivial to implement by overriding dict.__setitem__()

    badda-bing baby!
     
    r, Aug 3, 2009
    #2
    1. Advertising

  3. kj

    Chris Rebert Guest

    On Mon, Aug 3, 2009 at 2:47 PM, r<> wrote:
    > On Aug 3, 4:07 pm, kj <> wrote:
    >> I use the term "no-clobber dict" to refer to a dictionary D with
    >> the especial property that if K is in D, then
    >>
    >>   D[K] = V
    >>
    >> will raise an exception unless V == D[K].  In other words, D[K]
    >> can be set if K doesn't exist already among D's keys, or if the
    >> assigned value is equal to the current value of D[K].  All other
    >> assignments to D[K] trigger an exception.
    >>
    >> The idea here is to detect inconsistencies in the data.
    >>
    >> This is a data structure I often need.  Before I re-invent the
    >> wheel, I thought I'd ask: is it already available?
    >>
    >> TIA!
    >>
    >> kynn

    >
    > Not sure if something like this already exists, but it would be
    > trivial to implement by overriding dict.__setitem__()


    That is, if you don't care about .update() not preserving the
    invariant. Otherwise, one will need to look at the UserDict module.

    Cheers,
    Chris
    --
    http://blog.rebertia.com
     
    Chris Rebert, Aug 3, 2009
    #3
  4. kj

    r Guest

    On Aug 3, 5:00 pm, Chris Rebert <> wrote:
    > On Mon, Aug 3, 2009 at 2:47 PM, r<> wrote:

    [snip]
    > > Not sure if something like this already exists, but it would be
    > > trivial to implement by overriding dict.__setitem__()

    >
    > That is, if you don't care about .update() not preserving the
    > invariant. Otherwise, one will need to look at the UserDict module.
    >
    > Cheers,
    > Chris
    > --http://blog.rebertia.com


    Good catch Chris. However since the OP said this was for testing
    purposes, i just *assumed* he would be smart enough *not* to call
    update() on the dict at hand ;-). But sometimes i need to be protected
    from myself too -- at least thats what my therapist keeps telling
    me :)
     
    r, Aug 4, 2009
    #4
  5. On Mon, 03 Aug 2009 21:07:32 +0000, kj wrote:

    > I use the term "no-clobber dict" to refer to a dictionary D with the
    > especial property that if K is in D, then
    >
    > D[K] = V
    >
    > will raise an exception unless V == D[K]. In other words, D[K] can be
    > set if K doesn't exist already among D's keys, or if the assigned value
    > is equal to the current value of D[K]. All other assignments to D[K]
    > trigger an exception.



    Coincidentally, I just built something very close to what you ask. Here
    it is:

    class ConstantNamespace(dict):
    """Dictionary with write-once keys."""
    def __delitem__(self, key):
    raise TypeError("can't unbind constants")
    def __setitem__(self, key, value):
    if key in self:
    raise TypeError("can't rebind constants")
    super(ConstantNamespace, self).__setitem__(key, value)
    def clear(self):
    raise TypeError('cannot unbind constants')
    def pop(self, key, *args):
    raise TypeError("cannot pop constants")
    def popitem(self):
    raise TypeError("cannot pop constants")
    def update(self, other):
    for key in other:
    if key in self:
    raise TypeError('cannot update constants')
    # If we get here, then we're not modifying anything,
    # so okay to proceed.
    super(ConstantNamespace, self).update(other)
    def copy(self):
    c = self.__class__(**self)
    return c



    I also have a series of unit tests for it if you're interested in them.




    --
    Steven
     
    Steven D'Aprano, Aug 4, 2009
    #5
  6. kj

    alex23 Guest

    Steven D'Aprano <> wrote:
    > I also have a series of unit tests for it if you're interested in them.


    That's several times today that kj has asked a question and you've
    responded with ready-to-go code. If this was Stackoverflow, I'd accuse
    you of reputation-whoring...

    You _can_ just post your cool code without the double act, y'know! :)
     
    alex23, Aug 4, 2009
    #6
  7. kj

    kj Guest

    In <> Steven D'Aprano <> writes:

    >On Mon, 03 Aug 2009 21:07:32 +0000, kj wrote:


    >> I use the term "no-clobber dict" to refer to a dictionary D with the
    >> especial property that if K is in D, then
    >>
    >> D[K] = V
    >>
    >> will raise an exception unless V == D[K]. In other words, D[K] can be
    >> set if K doesn't exist already among D's keys, or if the assigned value
    >> is equal to the current value of D[K]. All other assignments to D[K]
    >> trigger an exception.



    >Coincidentally, I just built something very close to what you ask. Here
    >it is:


    >class ConstantNamespace(dict):
    > """Dictionary with write-once keys."""
    > def __delitem__(self, key):
    > raise TypeError("can't unbind constants")
    > def __setitem__(self, key, value):
    > if key in self:
    > raise TypeError("can't rebind constants")
    > super(ConstantNamespace, self).__setitem__(key, value)
    > def clear(self):
    > raise TypeError('cannot unbind constants')
    > def pop(self, key, *args):
    > raise TypeError("cannot pop constants")
    > def popitem(self):
    > raise TypeError("cannot pop constants")
    > def update(self, other):
    > for key in other:
    > if key in self:
    > raise TypeError('cannot update constants')
    > # If we get here, then we're not modifying anything,
    > # so okay to proceed.
    > super(ConstantNamespace, self).update(other)
    > def copy(self):
    > c = self.__class__(**self)
    > return c



    Thanks. As you note this not quite what I'm looking for, but it's
    a good template for it.

    kynn
     
    kj, Aug 4, 2009
    #7
  8. kj

    kj Guest

    In <> Chris Rebert <> writes:

    >On Mon, Aug 3, 2009 at 2:47 PM, r<> wrote:
    >> On Aug 3, 4:07=C2=A0pm, kj <> wrote:
    >>> I use the term "no-clobber dict" to refer to a dictionary D with
    >>> the especial property that if K is in D, then
    >>>
    >>> =C2=A0 D[K] =3D V
    >>>
    >>> will raise an exception unless V =3D=3D D[K]. =C2=A0In other words, D[K]
    >>> can be set if K doesn't exist already among D's keys, or if the
    >>> assigned value is equal to the current value of D[K]. =C2=A0All other
    >>> assignments to D[K] trigger an exception.
    >>>
    >>> The idea here is to detect inconsistencies in the data.
    >>>
    >>> This is a data structure I often need. =C2=A0Before I re-invent the
    >>> wheel, I thought I'd ask: is it already available?
    >>>
    >>> TIA!
    >>>
    >>> kynn

    >>
    >> Not sure if something like this already exists, but it would be
    >> trivial to implement by overriding dict.__setitem__()


    >That is, if you don't care about .update() not preserving the
    >invariant.


    The implication here is that .update() does not in turn use
    ..__setitem__(), which I find a bit surprising.

    kynn
     
    kj, Aug 4, 2009
    #8
  9. kj

    kj Guest

    In <> Steven D'Aprano <> writes:

    >class ConstantNamespace(dict):

    <snip>

    >I also have a series of unit tests for it if you're interested in them.


    Actually, come to think of it, I think I'll take you up on this.
    I'd love to see those tests. Unit testing in Python is in area I
    need to work on.

    TIA!

    kynn
     
    kj, Aug 4, 2009
    #9
  10. kj

    Chris Rebert Guest

    On Tue, Aug 4, 2009 at 12:30 PM, kj<> wrote:
    > In <> Chris Rebert <> writes:
    >
    >>On Mon, Aug 3, 2009 at 2:47 PM, r<> wrote:
    >>> On Aug 3, 4:07=C2=A0pm, kj <> wrote:
    >>>> I use the term "no-clobber dict" to refer to a dictionary D with
    >>>> the especial property that if K is in D, then
    >>>>
    >>>> =C2=A0 D[K] =3D V
    >>>>
    >>>> will raise an exception unless V =3D=3D D[K]. =C2=A0In other words, D[K]
    >>>> can be set if K doesn't exist already among D's keys, or if the
    >>>> assigned value is equal to the current value of D[K]. =C2=A0All other
    >>>> assignments to D[K] trigger an exception.
    >>>>
    >>>> The idea here is to detect inconsistencies in the data.
    >>>>
    >>>> This is a data structure I often need. =C2=A0Before I re-invent the
    >>>> wheel, I thought I'd ask: is it already available?
    >>>>
    >>>> TIA!
    >>>>
    >>>> kynn
    >>>
    >>> Not sure if something like this already exists, but it would be
    >>> trivial to implement by overriding dict.__setitem__()

    >
    >>That is, if you don't care about .update() not preserving the
    >>invariant.

    >
    > The implication here is that .update() does not in turn use
    > .__setitem__(), which I find a bit surprising.


    The builtin types are allowed to take such shortcuts for performance reasons.

    Cheers,
    Chris
    --
    http://blog.rebertia.com
     
    Chris Rebert, Aug 4, 2009
    #10
  11. [kj]
    > The implication here is that .update() does not in turn use
    > .__setitem__(), which I find a bit surprising.


    It's never wise to make assumptions about this sort of thing.
    Every method in a class or type is allowed to directly access
    or modify its private, internal data. The implementation is
    free to choose whether to limit that access to a few accessors
    (i.e. getitem, setitem, delitem, len) or to let all of the
    methods have direct access to the underlying data structure.
    Even if accessors were used, the choice would be arbitrary
    (perhaps delitem() gets implemented in terms of pop() or somesuch).

    This is a basic for OO programming. Unless the class documentation
    promises to use particular hooks, the implementation is free to
    change in any way that doesn't violate the published API (this is
    one of the benefits of encapsulation and abstract data types).

    In general, if a subclass is overriding, rather than extending,
    then it should override *every* method that could be affected.


    Raymond
     
    Raymond Hettinger, Aug 4, 2009
    #11
  12. On Wed, 5 Aug 2009 06:01 am kj wrote:

    > In <> Steven
    > D'Aprano <> writes:
    >
    >>class ConstantNamespace(dict):

    > <snip>
    >
    >>I also have a series of unit tests for it if you're interested in them.

    >
    > Actually, come to think of it, I think I'll take you up on this.
    > I'd love to see those tests. Unit testing in Python is in area I
    > need to work on.



    No problem. Here you go:

    http://www.cybersource.com.au/users/steve/python/constants.py

    Comments welcome.



    --
    Steven
     
    Steven D'Aprano, Aug 5, 2009
    #12
  13. kj

    kj Guest

    kj, Aug 5, 2009
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Chris Riesbeck

    XMLEncoder can clobber arrays

    Chris Riesbeck, Dec 18, 2003, in forum: Java
    Replies:
    7
    Views:
    2,011
    Adam Jenkins
    Dec 19, 2003
  2. Barry Schwarz

    Re: memory clobber

    Barry Schwarz, Jul 1, 2003, in forum: C Programming
    Replies:
    0
    Views:
    755
    Barry Schwarz
    Jul 1, 2003
  3. Joseph Turian
    Replies:
    2
    Views:
    301
    Joseph Turian
    Mar 21, 2006
  4. bruce
    Replies:
    0
    Views:
    277
    bruce
    Jan 10, 2012
  5. PerlFAQ Server
    Replies:
    0
    Views:
    609
    PerlFAQ Server
    Feb 11, 2011
Loading...

Share This Page