dictionary initialization

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Weiguang Shi

    #1

    dictionary initialization

    Hi,

    With awk, I can do something like
    $ echo 'hello' |awk '{a[$1]++}END{for(i in a)print i, a[i]}'

    That is, a['hello'] was not there but allocated and initialized to
    zero upon reference.

    With Python, I got[color=blue][color=green][color=darkred]
    >>> b={}
    >>> b[1] = b[1] +1[/color][/color][/color]
    Traceback (most recent call last):
    File "<stdin>", line 1, in ?
    KeyError: 1

    That is, I have to initialize b[1] explicitly in the first place.

    Personally, I think

    a[i]++

    in awk is much more elegant than

    if i in a: a[i] += 1
    else: a[i] = 1

    I wonder how the latter is justified in Python.

    Thanks,
    Weiguang
  • Caleb Hattingh

    #2
    Re: dictionary initialization

    Hmm :)

    "b[1]" looks like a List (but you created a Dict)
    "b['1'] looks more like a Dict (but this is not what you used).

    If lists are your thing:
    [color=blue][color=green][color=darkred]
    >>> a = []
    >>> a.append(1)
    >>> a[/color][/color][/color]
    [1][color=blue][color=green][color=darkred]
    >>> a[0] += 1
    >>> a[/color][/color][/color]
    [2]

    If dicts are your thing:
    [color=blue][color=green][color=darkred]
    >>> b = {}
    >>> b['1'] = 1
    >>> b[/color][/color][/color]
    {'1': 1}[color=blue][color=green][color=darkred]
    >>> b['1'] += 1
    >>> b[/color][/color][/color]
    {'1': 2}

    Lists are ordered, Dicts are not.
    Dict entries accessed with 'string' keys, List entries accessed with a
    position integer.

    Which feature specifically do you want justification for?

    thx
    Caleb




    [color=blue]
    > With Python, I got[color=green][color=darkred]
    > >>> b={}
    > >>> b[1] = b[1] +1[/color][/color]
    > Traceback (most recent call last):
    > File "<stdin>", line 1, in ?
    > KeyError: 1
    >
    > That is, I have to initialize b[1] explicitly in the first place.
    >
    > Personally, I think
    >
    > a[i]++
    >
    > in awk is much more elegant than
    >
    > if i in a: a[i] += 1
    > else: a[i] = 1
    >
    > I wonder how the latter is justified in Python.
    >
    > Thanks,
    > Weiguang[/color]

    Comment

    • Bengt Richter

      #3
      Re: dictionary initialization

      On Thu, 25 Nov 2004 18:38:17 +0000 (UTC), wgshi@namao.cs. ualberta.ca (Weiguang Shi) wrote:
      [color=blue]
      >Hi,
      >
      >With awk, I can do something like
      > $ echo 'hello' |awk '{a[$1]++}END{for(i in a)print i, a[i]}'
      >
      >That is, a['hello'] was not there but allocated and initialized to
      >zero upon reference.
      >
      >With Python, I got[color=green][color=darkred]
      > >>> b={}
      > >>> b[1] = b[1] +1[/color][/color]
      > Traceback (most recent call last):
      > File "<stdin>", line 1, in ?
      > KeyError: 1
      >
      >That is, I have to initialize b[1] explicitly in the first place.
      >
      >Personally, I think
      >
      > a[i]++
      >
      >in awk is much more elegant than
      >
      > if i in a: a[i] += 1
      > else: a[i] = 1
      >
      >I wonder how the latter is justified in Python.
      >[/color]
      You wrote it, so you have to "justify" it ;-)

      While I agree that ++ and -- are handy abbreviations, and creating a key by default
      makes for concise notation, a[i]++ means you have to make some narrow assumptions -- i.e.,
      that you want to create a zero integer start value. You can certainly make a dict subclass
      that behaves that way if you want it:
      [color=blue][color=green][color=darkred]
      >>> class D(dict):[/color][/color][/color]
      ... def __getitem__(sel f, i):
      ... if i not in self: self[i] = 0
      ... return dict.__getitem_ _(self, i)
      ...[color=blue][color=green][color=darkred]
      >>> dink = D()
      >>> dink[/color][/color][/color]
      {}[color=blue][color=green][color=darkred]
      >>> dink['a'] +=1
      >>> dink[/color][/color][/color]
      {'a': 1}[color=blue][color=green][color=darkred]
      >>> dink['a'] +=1
      >>> dink[/color][/color][/color]
      {'a': 2}[color=blue][color=green][color=darkred]
      >>> dink['b'][/color][/color][/color]
      0[color=blue][color=green][color=darkred]
      >>> dink['b'][/color][/color][/color]
      0[color=blue][color=green][color=darkred]
      >>> dink[/color][/color][/color]
      {'a': 2, 'b': 0}


      Otherwise the usual ways are along the lines of
      [color=blue][color=green][color=darkred]
      >>> d = {}
      >>> d.setdefault('h ello',[0])[0] += 1
      >>> d[/color][/color][/color]
      {'hello': [1]}[color=blue][color=green][color=darkred]
      >>> d.setdefault('h ello',[0])[0] += 1
      >>> d[/color][/color][/color]
      {'hello': [2]}

      Or[color=blue][color=green][color=darkred]
      >>> d['hi'] = d.get('hi', 0) + 1
      >>> d[/color][/color][/color]
      {'hi': 1, 'hello': [2]}[color=blue][color=green][color=darkred]
      >>> d['hi'] = d.get('hi', 0) + 1
      >>> d[/color][/color][/color]
      {'hi': 2, 'hello': [2]}[color=blue][color=green][color=darkred]
      >>> d['hi'] = d.get('hi', 0) + 1
      >>> d[/color][/color][/color]
      {'hi': 3, 'hello': [2]}

      Or[color=blue][color=green][color=darkred]
      >>> for x in xrange(3):[/color][/color][/color]
      ... try: d['yo'] += 1
      ... except KeyError: d['yo'] = 1
      ... print d
      ...
      {'hi': 3, 'hello': [2], 'yo': 1}
      {'hi': 3, 'hello': [2], 'yo': 2}
      {'hi': 3, 'hello': [2], 'yo': 3}

      Regards,
      Bengt Richter

      Comment

      • Weiguang Shi

        #4
        Re: dictionary initialization

        Hi,

        In article <opsh1u2sow1js0 xs@news.telkoms a.net>, Caleb Hattingh wrote:[color=blue]
        > ...
        >Dict entries accessed with 'string' keys,[/color]
        Not necessarily. And doesn't make a difference in my question.
        [color=blue]
        > ...
        >
        >Which feature specifically do you want justification for?[/color]
        Have it your way: string-indexed dictionaries.
        [color=blue][color=green][color=darkred]
        >>> a={}
        >>> a['1']+=1[/color][/color][/color]
        Traceback (most recent call last):
        File "<stdin>", line 1, in ?
        KeyError: '1'

        a['1'] when it referenced, is detected non-existent but not
        automatically initialized so that it exists before adding 1 to its
        value.

        Weiguang

        Comment

        • Weiguang Shi

          #5
          Re: dictionary initialization

          Hi,

          In article <41a62df4.10030 31613@news.oz.n et>, Bengt Richter wrote:[color=blue]
          > On Thu, 25 Nov 2004 18:38:17 +0000 (UTC), wgshi@namao.cs. ualberta.ca
          > (Weiguang Shi) wrote:
          >You wrote it, so you have to "justify" it ;-)[/color]
          I guess :-)
          [color=blue]
          >While I agree that ++ and -- are handy abbreviations, and creating a
          >key by default makes for concise notation, a[i]++ means you have to
          >make some narrow assumptions ...[/color]
          Right, though generalization can be painful for the uninitiated/newbie.
          [color=blue]
          >You can certainly make a dict subclass that behaves that way if you
          >want it:
          > ...[/color]
          This is nice even for someone hopelessly lazy as me.
          [color=blue]
          >
          >Otherwise the usual ways are along the lines of
          >...[/color]
          I would happily avoid them all.

          Thanks a lot,
          Weiguang

          Comment

          • Caleb Hattingh

            #6
            Re: dictionary initialization

            Hi

            I apologise, but I don't actually know what the problem is? If you could
            restate it a little, that would help.

            I didn't check the code I posted earlier; This below is checked:
            ***
            # Dont use a={}, just start as below
            '>>> a['1']=0
            '>>> a['1']+=1
            '>>> a
            {'1': 1}
            ***

            Like I said, I am unsure of what your specific problem is?

            Thanks
            Caleb


            On Thu, 25 Nov 2004 19:27:46 +0000 (UTC), Weiguang Shi
            <wgshi@namao.cs .ualberta.ca> wrote:
            [color=blue]
            > Hi,
            >
            > In article <opsh1u2sow1js0 xs@news.telkoms a.net>, Caleb Hattingh wrote:[color=green]
            >> ...
            >> Dict entries accessed with 'string' keys,[/color]
            > Not necessarily. And doesn't make a difference in my question.
            >[color=green]
            >> ...
            >>
            >> Which feature specifically do you want justification for?[/color]
            > Have it your way: string-indexed dictionaries.
            >[color=green][color=darkred]
            > >>> a={}
            > >>> a['1']+=1[/color][/color]
            > Traceback (most recent call last):
            > File "<stdin>", line 1, in ?
            > KeyError: '1'
            >
            > a['1'] when it referenced, is detected non-existent but not
            > automatically initialized so that it exists before adding 1 to its
            > value.
            >
            > Weiguang[/color]

            Comment

            • Caleb Hattingh

              #7
              Re: dictionary initialization

              And I haven't even been drinking!

              I apologise once more, this is better:

              ***
              # You *must* use a={}, just start as below
              '>>> a={}
              '>>> a['1']=0
              '>>> a['1']+=1
              '>>> a
              {'1': 1}
              ***

              Like I said, I am unsure of what your specific problem is?

              Thanks
              Caleb

              Comment

              • Dan Perl

                #8
                Re: dictionary initialization

                I don't know awk, so I don't know how your awk statement works.

                Even when it comes to the python statements, I'm not sure exactly what the
                intentions of design intention were in this case, but I can see at least one
                justification. Python being dynamically typed, b[1] can be of any type, so
                you have to initialize b[1] to give it a type and only then adding something
                to it makes sense. Otherwise, the 'add' operation not being implemented for
                all types, 'b[1]+1' may not even be allowed.

                You're saying that in awk a['hello'] is initialized to 0. That would not be
                justified in python. The type of b[1] is undetermined until initialization
                and I don't see why it should be an int by default.

                Dan

                "Weiguang Shi" <wgshi@namao.cs .ualberta.ca> wrote in message
                news:slrncqc9kq .hj3.wgshi@nama o.cs.ualberta.c a...[color=blue]
                > Hi,
                >
                > With awk, I can do something like
                > $ echo 'hello' |awk '{a[$1]++}END{for(i in a)print i, a[i]}'
                >
                > That is, a['hello'] was not there but allocated and initialized to
                > zero upon reference.
                >
                > With Python, I got[color=green][color=darkred]
                > >>> b={}
                > >>> b[1] = b[1] +1[/color][/color]
                > Traceback (most recent call last):
                > File "<stdin>", line 1, in ?
                > KeyError: 1
                >
                > That is, I have to initialize b[1] explicitly in the first place.
                >
                > Personally, I think
                >
                > a[i]++
                >
                > in awk is much more elegant than
                >
                > if i in a: a[i] += 1
                > else: a[i] = 1
                >
                > I wonder how the latter is justified in Python.
                >
                > Thanks,
                > Weiguang[/color]


                Comment

                • Weiguang Shi

                  #9
                  Re: dictionary initialization

                  In article <lIydnVF-WvXK3TvcRVn-jA@rogers.com>, Dan Perl wrote:[color=blue]
                  >I don't know awk, so I don't know how your awk statement works.[/color]
                  It doesn't hurt to give it a try :-)
                  [color=blue]
                  >
                  >Even when it comes to the python statements, I'm not sure exactly what the
                  > ...[/color]
                  I see your point.
                  [color=blue]
                  >
                  >You're saying that in awk a['hello'] is initialized to 0.[/color]
                  More than that; I said awk recognizes a['hello']++ as an
                  arithmetic operation and initializes a['hello'] to 0 and add one to
                  it. (This is all guess. I didn't implement gawk. But you see my point.)
                  [color=blue]
                  > That would not be justified in python. The type of b[1] is
                  > undetermined until initialization and I don't see why it should be
                  > an int by default.[/color]
                  In my example, it was b[1]+=1. "+=1" should at least tell Python two
                  things: this is an add operation and one of the operands is an
                  integer. Based on these, shouldn't Python be able to insert the pair
                  "1:0" into a{} before doing the increment?

                  Weiguang

                  Comment

                  • Weiguang Shi

                    #10
                    Re: dictionary initialization

                    Hi,

                    In article <opsh1wxfkx1js0 xs@news.telkoms a.net>, Caleb Hattingh wrote:[color=blue]
                    > ...
                    > ***
                    > # You *must* use a={}, just start as below
                    > '>>> a={}[/color]
                    Yeah I know. I can live with that.
                    [color=blue]
                    > '>>> a['1']=0
                    > '>>> a['1']+=1[/color]
                    Right here. You have to say a['1'] = 0 before you can say a['1'] +=1
                    Python does not do the former for you. That's what I'm asking
                    justifications for.

                    Regards,
                    Weiguang

                    Comment

                    • Peter Hansen

                      #11
                      Re: dictionary initialization

                      Weiguang Shi wrote:[color=blue]
                      > In article <lIydnVF-WvXK3TvcRVn-jA@rogers.com>, Dan Perl wrote:[color=green]
                      >>That would not be justified in python. The type of b[1] is
                      >>undetermine d until initialization and I don't see why it should be
                      >>an int by default.[/color]
                      >
                      > In my example, it was b[1]+=1. "+=1" should at least tell Python two
                      > things: this is an add operation and one of the operands is an
                      > integer.[/color]

                      Why would it tell Python that?
                      [color=blue][color=green][color=darkred]
                      >>> b = {1: 2.5}
                      >>> b[1] += 1
                      >>> b[/color][/color][/color]
                      {1: 3.5}

                      So at this point, it can clearly be either an integer or
                      a float. Doubtless it could also be an object which
                      overloads the += operator with integer arguments, though
                      what it might actually do is anyone's guess.

                      -Peter

                      Comment

                      • Berthold Höllmann

                        #12
                        Re: dictionary initialization

                        wgshi@namao.cs. ualberta.ca (Weiguang Shi) writes:
                        [color=blue]
                        > Hi,
                        >
                        > With awk, I can do something like
                        > $ echo 'hello' |awk '{a[$1]++}END{for(i in a)print i, a[i]}'
                        >
                        > That is, a['hello'] was not there but allocated and initialized to
                        > zero upon reference.
                        >
                        > With Python, I got[color=green][color=darkred]
                        > >>> b={}
                        > >>> b[1] = b[1] +1[/color][/color]
                        > Traceback (most recent call last):
                        > File "<stdin>", line 1, in ?
                        > KeyError: 1
                        >
                        > That is, I have to initialize b[1] explicitly in the first place.
                        >
                        > Personally, I think
                        >
                        > a[i]++
                        >
                        > in awk is much more elegant than
                        >
                        > if i in a: a[i] += 1
                        > else: a[i] = 1
                        >
                        > I wonder how the latter is justified in Python.[/color]

                        It isn't :-)
                        [color=blue][color=green][color=darkred]
                        >>> a={}
                        >>> a[1] = a.get(1, 0) + 1
                        >>> a[/color][/color][/color]
                        {1: 1}[color=blue][color=green][color=darkred]
                        >>> a[1] = a.get(1, 0) + 1
                        >>> a[/color][/color][/color]
                        {1: 2}

                        Regards
                        Berthold
                        --
                        berthold@xn--hllmanns-n4a.de / <http://höllmanns.de/>
                        bhoel@web.de / <http://starship.python .net/crew/bhoel/>

                        Comment

                        • Josiah Carlson

                          #13
                          Re: dictionary initialization


                          wgshi@namao.cs. ualberta.ca (Weiguang Shi) wrote:[color=blue]
                          >
                          > In article <lIydnVF-WvXK3TvcRVn-jA@rogers.com>, Dan Perl wrote:[color=green]
                          > >I don't know awk, so I don't know how your awk statement works.[/color]
                          > It doesn't hurt to give it a try :-)
                          >[color=green]
                          > >
                          > >Even when it comes to the python statements, I'm not sure exactly what the
                          > > ...[/color]
                          > I see your point.
                          >[color=green]
                          > >
                          > >You're saying that in awk a['hello'] is initialized to 0.[/color]
                          > More than that; I said awk recognizes a['hello']++ as an
                          > arithmetic operation and initializes a['hello'] to 0 and add one to
                          > it. (This is all guess. I didn't implement gawk. But you see my point.)
                          >[color=green]
                          > > That would not be justified in python. The type of b[1] is
                          > > undetermined until initialization and I don't see why it should be
                          > > an int by default.[/color]
                          > In my example, it was b[1]+=1. "+=1" should at least tell Python two
                          > things: this is an add operation and one of the operands is an
                          > integer. Based on these, shouldn't Python be able to insert the pair
                          > "1:0" into a{} before doing the increment?[/color]

                          As Peter has already mentioned, since b[1] doesn't exist until you
                          assign it, the type of b[1] is ambiguous.

                          The reason Python doesn't do automatic assignments on unknown access is
                          due to a few Python 'Zens'
                          [color=blue][color=green][color=darkred]
                          >>> import this[/color][/color][/color]
                          The Zen of Python, by Tim Peters

                          Beautiful is better than ugly.
                          Explicit is better than implicit.
                          Simple is better than complex.
                          Complex is better than complicated.
                          Flat is better than nested.
                          Sparse is better than dense.
                          Readability counts.
                          Special cases aren't special enough to break the rules.
                          Although practicality beats purity.
                          Errors should never pass silently.
                          Unless explicitly silenced.
                          In the face of ambiguity, refuse the temptation to guess.
                          There should be one-- and preferably only one --obvious way to do it.
                          Although that way may not be obvious at first unless you're Dutch.
                          Now is better than never.
                          Although never is often better than *right* now.
                          If the implementation is hard to explain, it's a bad idea.
                          If the implementation is easy to explain, it may be a good idea.
                          Namespaces are one honking great idea -- let's do more of those!

                          Specifically:
                          Explicit is better than implicit.
                          (you should assign what you want, not expect Python to know what you
                          want)
                          Special cases aren't special enough to break the rules.
                          (incrementing non-existant values in a dictionary shouldn't be any
                          different from accessing non-existant values)
                          In the face of ambiguity, refuse the temptation to guess.
                          (what class/value should the non-existant value initialize to?)


                          Learn the zens. Any time you have a design question about the Python,
                          check the zens, then check google, then check here.

                          - Josiah

                          Comment

                          • Weiguang Shi

                            #14
                            Re: dictionary initialization

                            I see.

                            Thanks
                            Weiguang

                            Comment

                            • Jeffrey Froman

                              #15
                              Re: dictionary initialization

                              Weiguang Shi wrote:
                              [color=blue]
                              > With awk, I can do something like
                              > $ echo 'hello' |awk '{a[$1]++}END{for(i in a)print i, a[i]}'
                              >
                              > That is, a['hello'] was not there but allocated and initialized to
                              > zero upon reference.
                              >
                              > With Python ... <snip>
                              > I have to initialize b[1] explicitly in the first place.[/color]

                              You could use the dictionary's setdefault method, if your value is mutable:
                              [color=blue][color=green][color=darkred]
                              >>> b={}
                              >>> for n in xrange(100):[/color][/color][/color]
                              .... b.setdefault('f oo', [0])[0] += 1
                              ....[color=blue][color=green][color=darkred]
                              >>> b['foo'][0][/color][/color][/color]
                              100

                              Jeffrey

                              Comment

                              Working...