dictionary interface

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Antoon Pardon

    #1

    dictionary interface

    I'm writing a Tree class, which should behave a lot like a dictionary.

    In order to test this, I took the unittest from the source distribution
    for dictionaries and used it to test against my Tree class.

    Things are working out rather well, but I stumbled on a problem.

    this unittest tries to test for '==' and '<' operators. However I
    couldn't find anything in the documentation that defined how
    dictionaries should behave with respect to these operators.

    For the moment the best I can come up with is something like
    the following:

    class Tree:

    def __lt__(self, term):
    return set(self.iterit ems()) < set(term.iterit ems())

    def __eq__(self, term):
    return set(self.iterit ems()) == set(term.iterit ems())

    Would this be a correct definition of the desired behaviour?

    Anyone a reference?

    --
    Antoon Pardon
  • Robert Kern

    #2
    Re: dictionary interface

    Antoon Pardon wrote:[color=blue]
    > I'm writing a Tree class, which should behave a lot like a dictionary.
    >
    > In order to test this, I took the unittest from the source distribution
    > for dictionaries and used it to test against my Tree class.
    >
    > Things are working out rather well, but I stumbled on a problem.
    >
    > this unittest tries to test for '==' and '<' operators. However I
    > couldn't find anything in the documentation that defined how
    > dictionaries should behave with respect to these operators.
    >
    > For the moment the best I can come up with is something like
    > the following:
    >
    > class Tree:
    >
    > def __lt__(self, term):
    > return set(self.iterit ems()) < set(term.iterit ems())
    >
    > def __eq__(self, term):
    > return set(self.iterit ems()) == set(term.iterit ems())
    >
    > Would this be a correct definition of the desired behaviour?[/color]

    No.

    In [1]: {1:2} < {3:4}
    Out[1]: True

    In [2]: set({1:2}.iteri tems()) < set({3:4}.iteri tems())
    Out[2]: False
    [color=blue]
    > Anyone a reference?[/color]

    The function dict_compare in dictobject.c .

    --
    Robert Kern
    rkern@ucsd.edu

    "In the fields of hell where the grass grows high
    Are the graves of dreams allowed to die."
    -- Richard Harter

    Comment

    • Tom Anderson

      #3
      Re: dictionary interface

      On Tue, 4 Oct 2005, Robert Kern wrote:
      [color=blue]
      > Antoon Pardon wrote:
      >[color=green]
      >> class Tree:
      >>
      >> def __lt__(self, term):
      >> return set(self.iterit ems()) < set(term.iterit ems())
      >>
      >> def __eq__(self, term):
      >> return set(self.iterit ems()) == set(term.iterit ems())
      >>
      >> Would this be a correct definition of the desired behaviour?[/color]
      >
      > No.
      >
      > In [1]: {1:2} < {3:4}
      > Out[1]: True
      >
      > In [2]: set({1:2}.iteri tems()) < set({3:4}.iteri tems())
      > Out[2]: False
      >[color=green]
      >> Anyone a reference?[/color]
      >
      > The function dict_compare in dictobject.c .[/color]

      Well there's a really helpful answer. I'm intrigued, Robert - since you
      know the real answer to this question, why did you choose to tell the
      Antoon that he was wrong, not tell him in what way he was wrong, certainly
      not tell him how to be right, but just tell him to read the source, rather
      than simply telling him what you knew? Still, at least you told him which
      file to look in. And if he knows python but not C, or gets lost in the
      byzantine workings of the interpreter, well, that's his own fault, i
      guess.

      So, Antoon, firstly, your implementation of __eq__ is, i believe, correct.

      Your implementation of __lt__ is, sadly, not. While sets take "<" to mean
      "is a proper subset of", for dicts, it's a more conventional comparison
      operation, which constitutes a total ordering over all dicts (so you can
      sort with it, for example). However, since dicts don't really have a
      natural total ordering, it is ever so slightly arbitrary.

      The rules for ordering on dicts are, AFAICT:

      - If one dict has fewer elements than the other, it's the lesser
      - If not, find the smallest key for which the two dicts have different
      values (counting 'not present' as a value)
      -- If there is no such key, the dicts are equal
      -- If the key is present in one dict but not the other, the dict in which
      it is present is the lesser
      -- Otherwise, the dict in which the value is lesser is itself the lesser

      In code:

      def dict_cmp(a, b):
      diff = cmp(len(a), len(b))
      if (diff != 0):
      return diff
      for key in sorted(set(a.ke ys() + b.keys())):
      if (key not in a):
      return 1
      if (key not in b):
      return -1
      diff = cmp(a[key], b[key])
      if (diff != 0):
      return diff
      return 0

      I assume your tree has its items sorted by key value; that means there's
      an efficient implementation of this using lockstep iteration over the two
      trees being compared.

      Another way of looking at it is in terms of list comparisons: comparing
      two dicts is the same as comparing the sorted list of keys in each dict,
      breaking ties by looking at the list of values, in order of their keys.
      There's a quirk, in that a shorter dict is always less than a longer dict,
      regardless of the elements.

      In code:

      def dict_cmp_altern ative(a, b):
      diff = cmp(len(a), len(b))
      if (diff != 0):
      return diff
      ka = sorted(a.keys() )
      kb = sorted(b.keys() )
      diff = cmp(ka, kb)
      if (diff != 0):
      return diff
      va = [a[k] for k in ka]
      vb = [b[k] for k in kb]
      return cmp(va, vb)

      Hope this helps.

      tom

      PS In case it's of any use to you, here's the code i used to test these:

      import random

      def rnd(n):
      return random.randint( 0, n)

      def randomdict(maxl en=20, range=100):
      return dict((rnd(range ), rnd(range)) for x in xrange(rnd(maxl en)))

      def test(cmp2, n=1000):
      for i in xrange(n):
      a = randomdict()
      b = randomdict()
      if ((cmp(a, b)) != (cmp2(a, b))):
      raise AssertionError, (a, b)

      --
      What we learn about is not nature itself, but nature exposed to our methods of questioning. -- Werner Heisenberg

      Comment

      • Robert Kern

        #4
        Re: dictionary interface

        Tom Anderson wrote:[color=blue]
        > On Tue, 4 Oct 2005, Robert Kern wrote:
        >[color=green]
        >>Antoon Pardon wrote:
        >>[color=darkred]
        >>> class Tree:
        >>>
        >>> def __lt__(self, term):
        >>> return set(self.iterit ems()) < set(term.iterit ems())
        >>>
        >>> def __eq__(self, term):
        >>> return set(self.iterit ems()) == set(term.iterit ems())
        >>>
        >>>Would this be a correct definition of the desired behaviour?[/color]
        >>
        >>No.
        >>
        >>In [1]: {1:2} < {3:4}
        >>Out[1]: True
        >>
        >>In [2]: set({1:2}.iteri tems()) < set({3:4}.iteri tems())
        >>Out[2]: False
        >>[color=darkred]
        >>>Anyone a reference?[/color]
        >>
        >>The function dict_compare in dictobject.c .[/color]
        >
        > Well there's a really helpful answer.[/color]

        Well, *I* thought it was. Maybe not "really" helpful, but certainly a
        healthy start.
        [color=blue]
        > I'm intrigued, Robert - since you
        > know the real answer to this question, why did you choose to tell the
        > Antoon that he was wrong, not tell him in what way he was wrong, certainly
        > not tell him how to be right, but just tell him to read the source, rather
        > than simply telling him what you knew?[/color]

        Because I *didn't* know. I *still* don't know. I just know that the
        implementation of __lt__ was wrong as I demonstrated by applying the
        given algorithm to real dictionaries. I *do* know where to find that
        information: the source. So I told him absolutely everything that I knew
        on the subject. I couldn't tell him anything more except by trudging
        through the details of the source myself, but I'm not particularly
        interested in learning those details myself, so I didn't bother.

        What do you want? Personalized Python tutorials delivered by candygram?
        A detailed comparison of the various partial ordering schemes that could
        have been used? My first born son?
        [color=blue]
        > Still, at least you told him which
        > file to look in.[/color]

        Yes, I figured it was the polite, helpful thing to do. Apparently, I
        shouldn't have bothered.
        [color=blue]
        > And if he knows python but not C, or gets lost in the
        > byzantine workings of the interpreter, well, that's his own fault, i
        > guess.[/color]

        It's certainly not mine.

        --
        Robert Kern
        rkern@ucsd.edu

        "In the fields of hell where the grass grows high
        Are the graves of dreams allowed to die."
        -- Richard Harter

        Comment

        • Antoon Pardon

          #5
          Re: dictionary interface

          Op 2005-10-05, Tom Anderson schreef <twic@urchin.ea rth.li>:[color=blue]
          > On Tue, 4 Oct 2005, Robert Kern wrote:
          >[color=green]
          >> Antoon Pardon wrote:
          >>[color=darkred]
          >>> class Tree:
          >>>
          >>> def __lt__(self, term):
          >>> return set(self.iterit ems()) < set(term.iterit ems())
          >>>
          >>> def __eq__(self, term):
          >>> return set(self.iterit ems()) == set(term.iterit ems())
          >>>
          >>> Would this be a correct definition of the desired behaviour?[/color]
          >>
          >> No.
          >>
          >> In [1]: {1:2} < {3:4}
          >> Out[1]: True
          >>
          >> In [2]: set({1:2}.iteri tems()) < set({3:4}.iteri tems())
          >> Out[2]: False
          >>[color=darkred]
          >>> Anyone a reference?[/color]
          >>
          >> The function dict_compare in dictobject.c .[/color]
          >
          > Well there's a really helpful answer. I'm intrigued, Robert - since you
          > know the real answer to this question, why did you choose to tell the
          > Antoon that he was wrong, not tell him in what way he was wrong, certainly
          > not tell him how to be right, but just tell him to read the source, rather
          > than simply telling him what you knew? Still, at least you told him which
          > file to look in. And if he knows python but not C, or gets lost in the
          > byzantine workings of the interpreter, well, that's his own fault, i
          > guess.
          >
          > So, Antoon, firstly, your implementation of __eq__ is, i believe, correct.
          >
          > Your implementation of __lt__ is, sadly, not. While sets take "<" to mean
          > "is a proper subset of", for dicts, it's a more conventional comparison
          > operation, which constitutes a total ordering over all dicts (so you can
          > sort with it, for example). However, since dicts don't really have a
          > natural total ordering, it is ever so slightly arbitrary.
          >
          > The rules for ordering on dicts are, AFAICT:
          >
          > - If one dict has fewer elements than the other, it's the lesser
          > - If not, find the smallest key for which the two dicts have different
          > values (counting 'not present' as a value)
          > -- If there is no such key, the dicts are equal
          > -- If the key is present in one dict but not the other, the dict in which
          > it is present is the lesser
          > -- Otherwise, the dict in which the value is lesser is itself the lesser
          >
          > In code:
          >
          > def dict_cmp(a, b):
          > diff = cmp(len(a), len(b))
          > if (diff != 0):
          > return diff
          > for key in sorted(set(a.ke ys() + b.keys())):
          > if (key not in a):
          > return 1
          > if (key not in b):
          > return -1
          > diff = cmp(a[key], b[key])
          > if (diff != 0):
          > return diff
          > return 0
          >[/color]

          Thanks for the explanation, but you somehow give me too much.

          I have been searching some more and finally stumbled on this:



          Mappings (dictionaries) compare equal if and only if their sorted
          (key, value) lists compare equal. Outcomes other than equality are
          resolved consistently, but are not otherwise defined.

          This seems to imply that the specific method to sort the dictionaries
          is unimported (as long as it is a total ordering). So I can use whatever
          method I want as long as it is achieves this.

          But that is contradicted by the unittest. If you have a unittest for
          comparing dictionaries, that means comparing dictionaries has a
          testable characteristic and thus is further defined.

          So I don't need a full implementation of dictionary comparison,
          I need to know in how far such a comparison is defined and
          what I can choose.

          --
          Antoon Pardon

          Comment

          • Paul Rubin

            #6
            Re: dictionary interface

            Antoon Pardon <apardon@forel. vub.ac.be> writes:[color=blue]
            > But that is contradicted by the unittest. If you have a unittest for
            > comparing dictionaries, that means comparing dictionaries has a
            > testable characteristic and thus is further defined.[/color]

            No, I don't think so. The unittest makes sure that a particular
            implementation works as intended. That doesn't mean that every part
            of the of how that particular implementation works is required by the
            language definition. It can have some non-required (but
            non-forbidden) characteristics and those could still get tested.

            Comment

            • Steve Holden

              #7
              Re: dictionary interface

              Antoon Pardon wrote:[color=blue]
              > Op 2005-10-05, Tom Anderson schreef <twic@urchin.ea rth.li>:
              >[color=green]
              >>On Tue, 4 Oct 2005, Robert Kern wrote:
              >>
              >>[color=darkred]
              >>>Antoon Pardon wrote:
              >>>
              >>>
              >>>> class Tree:
              >>>>
              >>>> def __lt__(self, term):
              >>>> return set(self.iterit ems()) < set(term.iterit ems())
              >>>>
              >>>> def __eq__(self, term):
              >>>> return set(self.iterit ems()) == set(term.iterit ems())
              >>>>
              >>>>Would this be a correct definition of the desired behaviour?
              >>>
              >>>No.
              >>>
              >>>In [1]: {1:2} < {3:4}
              >>>Out[1]: True
              >>>
              >>>In [2]: set({1:2}.iteri tems()) < set({3:4}.iteri tems())
              >>>Out[2]: False
              >>>
              >>>
              >>>>Anyone a reference?
              >>>
              >>>The function dict_compare in dictobject.c .[/color]
              >>
              >>Well there's a really helpful answer. I'm intrigued, Robert - since you
              >>know the real answer to this question, why did you choose to tell the
              >>Antoon that he was wrong, not tell him in what way he was wrong, certainly
              >>not tell him how to be right, but just tell him to read the source, rather
              >>than simply telling him what you knew? Still, at least you told him which
              >>file to look in. And if he knows python but not C, or gets lost in the
              >>byzantine workings of the interpreter, well, that's his own fault, i
              >>guess.
              >>
              >>So, Antoon, firstly, your implementation of __eq__ is, i believe, correct.
              >>
              >>Your implementation of __lt__ is, sadly, not. While sets take "<" to mean
              >>"is a proper subset of", for dicts, it's a more conventional comparison
              >>operation, which constitutes a total ordering over all dicts (so you can
              >>sort with it, for example). However, since dicts don't really have a
              >>natural total ordering, it is ever so slightly arbitrary.
              >>
              >>The rules for ordering on dicts are, AFAICT:
              >>
              >>- If one dict has fewer elements than the other, it's the lesser
              >>- If not, find the smallest key for which the two dicts have different
              >>values (counting 'not present' as a value)
              >>-- If there is no such key, the dicts are equal
              >>-- If the key is present in one dict but not the other, the dict in which
              >>it is present is the lesser
              >>-- Otherwise, the dict in which the value is lesser is itself the lesser
              >>
              >>In code:
              >>
              >>def dict_cmp(a, b):
              >> diff = cmp(len(a), len(b))
              >> if (diff != 0):
              >> return diff
              >> for key in sorted(set(a.ke ys() + b.keys())):
              >> if (key not in a):
              >> return 1
              >> if (key not in b):
              >> return -1
              >> diff = cmp(a[key], b[key])
              >> if (diff != 0):
              >> return diff
              >> return 0
              >>[/color]
              >
              >
              > Thanks for the explanation, but you somehow give me too much.
              >
              > I have been searching some more and finally stumbled on this:
              >
              > http://docs.python.org/ref/comparisons.html
              >
              > Mappings (dictionaries) compare equal if and only if their sorted
              > (key, value) lists compare equal. Outcomes other than equality are
              > resolved consistently, but are not otherwise defined.
              >
              > This seems to imply that the specific method to sort the dictionaries
              > is unimported (as long as it is a total ordering). So I can use whatever
              > method I want as long as it is achieves this.
              >
              > But that is contradicted by the unittest. If you have a unittest for
              > comparing dictionaries, that means comparing dictionaries has a
              > testable characteristic and thus is further defined.
              >
              > So I don't need a full implementation of dictionary comparison,
              > I need to know in how far such a comparison is defined and
              > what I can choose.
              >[/color]
              The dict unit tests are probably trying to ensure that the dictionary
              ordering doesn't change from version to version, which is probably a
              good idea in case someone (foolishly?) deciess to rely on it.

              I can't help wondering, though, under what conditions it actually makes
              sense to compare two dictionaries for anything other than equality.

              regards
              Steve
              --
              Steve Holden +44 150 684 7255 +1 800 494 3119
              Holden Web LLC www.holdenweb.com
              PyCon TX 2006 www.python.org/pycon/

              Comment

              • Antoon Pardon

                #8
                Re: dictionary interface

                Op 2005-10-05, Paul Rubin schreef <http>:[color=blue]
                > Antoon Pardon <apardon@forel. vub.ac.be> writes:[color=green]
                >> But that is contradicted by the unittest. If you have a unittest for
                >> comparing dictionaries, that means comparing dictionaries has a
                >> testable characteristic and thus is further defined.[/color]
                >
                > No, I don't think so. The unittest makes sure that a particular
                > implementation works as intended. That doesn't mean that every part
                > of the of how that particular implementation works is required by the
                > language definition.[/color]

                As far as I understand, unittest test for functionality clients should
                be able to rely on. They shouldn't be used to test a specific
                implementation feature.

                The idea is that if you change the implementation, you can quickly
                test the functionality is unharmed. But you can't do that if
                also specific implementation details are tested for.
                [color=blue]
                > It can have some non-required (but
                > non-forbidden) characteristics and those could still get tested.[/color]

                That doesn't seem to make sense. If it is not required it shouldn't
                be tested for, at least not in a unittest, because otherwise a new
                implementation that doesn't have the non-required characteristics
                will be rejected.

                My tree class is almost finished, but one unittest still fails,
                is this a failing of my class (as a replacement for a dictionary)
                or is this a non-required characteristic of dictionaries?

                --
                Antoon Pardon

                Comment

                • Paul Rubin

                  #9
                  Re: dictionary interface

                  Steve Holden <steve@holdenwe b.com> writes:[color=blue]
                  > I can't help wondering, though, under what conditions it actually
                  > makes sense to compare two dictionaries for anything other than
                  > equality.[/color]

                  You might want to sort a bunch of dictionaries to bring the equal ones
                  together.

                  Comment

                  • Paul Rubin

                    #10
                    Re: dictionary interface

                    Antoon Pardon <apardon@forel. vub.ac.be> writes:[color=blue]
                    > My tree class is almost finished, but one unittest still fails,
                    > is this a failing of my class (as a replacement for a dictionary)
                    > or is this a non-required characteristic of dictionaries?[/color]

                    If it were me, I'd treat the language reference manual as
                    authoritative. YMMV.

                    Comment

                    • Antoon Pardon

                      #11
                      Re: dictionary interface

                      Op 2005-10-05, Steve Holden schreef <steve@holdenwe b.com>:[color=blue]
                      > Antoon Pardon wrote:[color=green]
                      >>
                      >> I have been searching some more and finally stumbled on this:
                      >>
                      >> http://docs.python.org/ref/comparisons.html
                      >>
                      >> Mappings (dictionaries) compare equal if and only if their sorted
                      >> (key, value) lists compare equal. Outcomes other than equality are
                      >> resolved consistently, but are not otherwise defined.
                      >>
                      >> This seems to imply that the specific method to sort the dictionaries
                      >> is unimported (as long as it is a total ordering). So I can use whatever
                      >> method I want as long as it is achieves this.
                      >>
                      >> But that is contradicted by the unittest. If you have a unittest for
                      >> comparing dictionaries, that means comparing dictionaries has a
                      >> testable characteristic and thus is further defined.
                      >>
                      >> So I don't need a full implementation of dictionary comparison,
                      >> I need to know in how far such a comparison is defined and
                      >> what I can choose.
                      >>[/color]
                      > The dict unit tests are probably trying to ensure that the dictionary
                      > ordering doesn't change from version to version, which is probably a
                      > good idea in case someone (foolishly?) deciess to rely on it.[/color]

                      I doubt that. Just to check I tried the following:

                      class Tree:

                      def __lt__(self, term):
                      return len(self) < len(term)

                      And the test passed.
                      [color=blue]
                      > I can't help wondering, though, under what conditions it actually makes
                      > sense to compare two dictionaries for anything other than equality.[/color]

                      Yes that is part of the problem, because I can't think of such a
                      condition it is hard to think of what extra constraints could be
                      usefull here.

                      Anyway, I have searched the source of the test for all testing
                      with regards to < and after some browsing back and fore it seems
                      it all boils down to the following two tests.

                      self.assert_(no t {} < {})
                      self.assert_(no t {1: 2} < {1L: 2L})

                      --
                      Antoon Pardon

                      Comment

                      • Steve Holden

                        #12
                        Re: dictionary interface

                        Antoon Pardon wrote:[color=blue]
                        > Op 2005-10-05, Steve Holden schreef <steve@holdenwe b.com>:[/color]
                        [...][color=blue]
                        >
                        > Anyway, I have searched the source of the test for all testing
                        > with regards to < and after some browsing back and fore it seems
                        > it all boils down to the following two tests.
                        >
                        > self.assert_(no t {} < {})
                        > self.assert_(no t {1: 2} < {1L: 2L})
                        >[/color]

                        So there isn't much to do, then! That's good. Seems you can pretty much
                        choose your own ordering.

                        It would seem sensible to test a third case, namely

                        self.assert_(no t {1L: 2L} < {1: 2})

                        regards
                        Steve
                        --
                        Steve Holden +44 150 684 7255 +1 800 494 3119
                        Holden Web LLC www.holdenweb.com
                        PyCon TX 2006 www.python.org/pycon/

                        Comment

                        • Tom Anderson

                          #13
                          Re: dictionary interface

                          On Tue, 4 Oct 2005, Robert Kern wrote:
                          [color=blue]
                          > Tom Anderson wrote:[color=green]
                          >> On Tue, 4 Oct 2005, Robert Kern wrote:
                          >>[color=darkred]
                          >>> Antoon Pardon wrote:
                          >>>
                          >>>> Anyone a reference?
                          >>>
                          >>> The function dict_compare in dictobject.c .[/color]
                          >>
                          >> Well there's a really helpful answer.[/color]
                          >
                          > Well, *I* thought it was.[/color]

                          And indeed it was. I'm sorry i was so rude - i must have been in a bad
                          mood. My apologies.
                          [color=blue]
                          > What do you want? Personalized Python tutorials delivered by candygram?[/color]

                          YES DAMMIT! WITH BIG KISS FROM GUIDO!

                          tom

                          --
                          The revolution is here. Get against the wall, sunshine. -- Mike Froggatt

                          Comment

                          • Bengt Richter

                            #14
                            Re: dictionary interface

                            On 5 Oct 2005 08:23:53 GMT, Antoon Pardon <apardon@forel. vub.ac.be> wrote:
                            [color=blue]
                            >Op 2005-10-05, Tom Anderson schreef <twic@urchin.ea rth.li>:[color=green]
                            >> On Tue, 4 Oct 2005, Robert Kern wrote:
                            >>[color=darkred]
                            >>> Antoon Pardon wrote:
                            >>>
                            >>>> class Tree:
                            >>>>
                            >>>> def __lt__(self, term):
                            >>>> return set(self.iterit ems()) < set(term.iterit ems())
                            >>>>
                            >>>> def __eq__(self, term):
                            >>>> return set(self.iterit ems()) == set(term.iterit ems())
                            >>>>
                            >>>> Would this be a correct definition of the desired behaviour?
                            >>>
                            >>> No.
                            >>>
                            >>> In [1]: {1:2} < {3:4}
                            >>> Out[1]: True
                            >>>
                            >>> In [2]: set({1:2}.iteri tems()) < set({3:4}.iteri tems())
                            >>> Out[2]: False
                            >>>
                            >>>> Anyone a reference?
                            >>>
                            >>> The function dict_compare in dictobject.c .[/color]
                            >>
                            >> Well there's a really helpful answer. I'm intrigued, Robert - since you
                            >> know the real answer to this question, why did you choose to tell the
                            >> Antoon that he was wrong, not tell him in what way he was wrong, certainly
                            >> not tell him how to be right, but just tell him to read the source, rather
                            >> than simply telling him what you knew? Still, at least you told him which
                            >> file to look in. And if he knows python but not C, or gets lost in the
                            >> byzantine workings of the interpreter, well, that's his own fault, i
                            >> guess.
                            >>
                            >> So, Antoon, firstly, your implementation of __eq__ is, i believe, correct.
                            >>
                            >> Your implementation of __lt__ is, sadly, not. While sets take "<" to mean
                            >> "is a proper subset of", for dicts, it's a more conventional comparison
                            >> operation, which constitutes a total ordering over all dicts (so you can
                            >> sort with it, for example). However, since dicts don't really have a
                            >> natural total ordering, it is ever so slightly arbitrary.
                            >>
                            >> The rules for ordering on dicts are, AFAICT:
                            >>
                            >> - If one dict has fewer elements than the other, it's the lesser
                            >> - If not, find the smallest key for which the two dicts have different
                            >> values (counting 'not present' as a value)
                            >> -- If there is no such key, the dicts are equal
                            >> -- If the key is present in one dict but not the other, the dict in which
                            >> it is present is the lesser
                            >> -- Otherwise, the dict in which the value is lesser is itself the lesser
                            >>
                            >> In code:
                            >>
                            >> def dict_cmp(a, b):
                            >> diff = cmp(len(a), len(b))
                            >> if (diff != 0):
                            >> return diff
                            >> for key in sorted(set(a.ke ys() + b.keys())):
                            >> if (key not in a):
                            >> return 1
                            >> if (key not in b):
                            >> return -1
                            >> diff = cmp(a[key], b[key])
                            >> if (diff != 0):
                            >> return diff
                            >> return 0
                            >>[/color]
                            >
                            >Thanks for the explanation, but you somehow give me too much.
                            >
                            >I have been searching some more and finally stumbled on this:
                            >
                            >http://docs.python.org/ref/comparisons.html
                            >
                            > Mappings (dictionaries) compare equal if and only if their sorted
                            > (key, value) lists compare equal. Outcomes other than equality are
                            > resolved consistently, but are not otherwise defined.
                            >[/color]
                            "other outcomes" may not in general mean orderings are defined,
                            even when == and != are well defined. E.g., below
                            [color=blue]
                            >This seems to imply that the specific method to sort the dictionaries
                            >is unimported (as long as it is a total ordering). So I can use whatever
                            >method I want as long as it is achieves this.
                            >
                            >But that is contradicted by the unittest. If you have a unittest for
                            >comparing dictionaries, that means comparing dictionaries has a
                            >testable characteristic and thus is further defined.
                            >
                            >So I don't need a full implementation of dictionary comparison,
                            >I need to know in how far such a comparison is defined and
                            >what I can choose.
                            >[/color]
                            A couple of data points that may be of interest:
                            [color=blue][color=green][color=darkred]
                            >>> {'a':0j} < {'a':1j}[/color][/color][/color]
                            Traceback (most recent call last):
                            File "<stdin>", line 1, in ?
                            TypeError: cannot compare complex numbers using <, <=, >, >=

                            and[color=blue][color=green][color=darkred]
                            >>> cmp(0j, 1j)[/color][/color][/color]
                            Traceback (most recent call last):
                            File "<stdin>", line 1, in ?
                            TypeError: cannot compare complex numbers using <, <=, >, >=

                            but[color=blue][color=green][color=darkred]
                            >>> {'a':0j} == {'a':1j}[/color][/color][/color]
                            False[color=blue][color=green][color=darkred]
                            >>> {'a':1j} == {'a':1j}[/color][/color][/color]
                            True

                            Regards,
                            Bengt Richter

                            Comment

                            • Antoon Pardon

                              #15
                              Re: dictionary interface

                              Op 2005-10-05, Steve Holden schreef <steve@holdenwe b.com>:[color=blue]
                              > Antoon Pardon wrote:[color=green]
                              >> Op 2005-10-05, Steve Holden schreef <steve@holdenwe b.com>:[/color]
                              > [...][color=green]
                              >>
                              >> Anyway, I have searched the source of the test for all testing
                              >> with regards to < and after some browsing back and fore it seems
                              >> it all boils down to the following two tests.
                              >>
                              >> self.assert_(no t {} < {})
                              >> self.assert_(no t {1: 2} < {1L: 2L})
                              >>[/color]
                              >
                              > So there isn't much to do, then! That's good. Seems you can pretty much
                              > choose your own ordering.[/color]

                              Yes, I must have misunderstood something because I thought there also
                              was the following test:

                              self.assert_({} < {1: 2})

                              Which is what prompted this thread from me.
                              [color=blue]
                              > It would seem sensible to test a third case, namely
                              >
                              > self.assert_(no t {1L: 2L} < {1: 2})[/color]

                              I also though about adding the following test.

                              dlst = range(20)
                              for i in xrange(20):
                              dlst[i] = some_ramdom_dic t()
                              sort(dlst)
                              for i in xrange(19):
                              for j in xrange(i+1,20):
                              self.assert_(dl st[i] < dlst[j])


                              This would test for the consistency of the order, so that if a < b
                              and b < c that we also have a < c.

                              What do you think?

                              --
                              Antoon Pardon

                              Comment

                              Working...