Concise idiom to initialize dictionaries

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Frohnhofer, James

    #1

    Concise idiom to initialize dictionaries

    My initial problem was to initialize a bunch of dictionaries at the start of a
    function.

    I did not want to do
    def fn():
    a = {}
    b = {}
    c = {}
    . . .
    z = {}
    simply because it was ugly and wasted screen space.

    First I tried:

    for x in (a,b,c,d,e,f,g) : x = {}

    which didn't work (but frankly I didn't really expect it to.)
    Then I tried:

    for x in ('a','b','c','d ','e','f','g'): locals()[x]={}

    which did what I wanted, in the interpreter. When I put it inside a function,
    it doesn't seem to work. If I print locals() from inside the function, I can
    see them, and they appear to be fine, but the first time I try to access one
    of them I get a "NameError: global name 'a' is not defined"

    Now obviously I could easily avoid this problem by just initializing each
    dictionary, but is there something wrong about my understanding of locals,
    that my function isn't behaving the way I expect?


    [color=blue]
    > -----Original Message-----
    > From: python-list-bounces+james.f rohnhofer=csfb. com@python.org
    > [mailto:python-list-bounces+james.f rohnhofer=csfb. com@python.org]On
    > Behalf Of Dennis Lee Bieber
    > Sent: Tuesday, November 09, 2004 10:31 AM
    > To: python-list@python.org
    > Subject: Re: Determining combination of bits
    >
    >
    > On Mon, 8 Nov 2004 21:18:36 -0800, "news.west.cox. net"
    > <sean.berry2@co x.net> declaimed the following in comp.lang.pytho n:
    >[color=green][color=darkred]
    > > > Note: 2^1 = 2, so your dictionary is already in error...
    > > >[/color]
    > >
    > > The dictionary was filled with arbitrary values, not
    > > { x : 2^x } values like you might have thought.[/color]
    >
    > Well, you had stated "powers of two"... If all you wanted is a
    > bit mapping you could probably drop the dictionary and just use a list
    > of the values, indexed by the bit position, and my first attempt
    > logic...
    >[color=green]
    > >
    > > It is actually more like {1:123, 2:664, 4:323, 8:990, 16:221... etc}
    > >
    > >[/color]
    >
    > CheckBoxes = [ "FirstChoic e",
    > "SecondChoi ce",
    > "ThirdChoic e",
    > "FourthChoi ce",
    > "FifthChoic e",
    > "SixthChoic e" ]
    >
    >
    > for num in [22, 25, 9]:
    > bit = 0
    > while num:
    > if num & 1:
    > print CheckBoxes[bit],
    > bit = bit + 1
    > num = num >> 1
    > print
    >
    > SecondChoice ThirdChoice FifthChoice
    > FirstChoice FourthChoice FifthChoice
    > FirstChoice FourthChoice
    >
    > where "num" is the sum of the checkbox index values (or whatever
    > selection mechanism is used), assuming /they/ were set up in 2^(n+1)
    > scheme (n = bit position, starting with 0)...
    >
    > --[color=green]
    > > =============== =============== =============== =============== == <
    > > wlfraed@ix.netc om.com | Wulfraed Dennis Lee Bieber KD6MOG <
    > > wulfraed@dm.net | Bestiaria Support Staff <
    > > =============== =============== =============== =============== == <
    > > Home Page: <http://www.dm.net/~wulfraed/> <
    > > Overflow Page: <http://wlfraed.home.ne tcom.com/> <[/color]
    > --
    > http://mail.python.org/mailman/listinfo/python-list
    >[/color]

    =============== =============== =============== =============== =============== ===
    This message is for the sole use of the intended recipient. If you received
    this message in error please delete it and notify us. If this message was
    misdirected, CSFB does not waive any confidentiality or privilege. CSFB
    retains and monitors electronic communications sent through its network.
    Instructions transmitted over this system are not binding on CSFB until they
    are confirmed by us. Message transmission is not guaranteed to be secure.
    =============== =============== =============== =============== =============== ===

  • Larry Bates

    #2
    Re: Concise idiom to initialize dictionaries

    It is almost certain that you should use either a list of dictionaries
    or a dictionary containing other dictionaries for this. Creation of
    26 distinct dictionaries is almost never a good solution as it makes
    it nearly impossible to iterate over them and would make code to
    manipulate them unable to be generalized easily.

    Example:

    #
    # To create a list of dictionaries
    #
    list_of_dicts=[]
    for i in range(26):
    list_of_dicts.a ppend({})

    #
    # Now you can reference each dictionary as:
    #
    # list_of_dicts[0], list_of_dicts[1], ...
    #

    or

    import string
    dict_of_dicts={ }
    for letter in string.ascii_lo wercase:
    dict_of_dicts[letter]={}

    #
    # Now you can reference each dictionary as:
    #
    # dict_of_dicts['a'], dict_of_dicts['b'], ...

    Larry Bates


    Frohnhofer, James wrote:[color=blue]
    > My initial problem was to initialize a bunch of dictionaries at the start of a
    > function.
    >
    > I did not want to do
    > def fn():
    > a = {}
    > b = {}
    > c = {}
    > . . .
    > z = {}
    > simply because it was ugly and wasted screen space.
    >
    > First I tried:
    >
    > for x in (a,b,c,d,e,f,g) : x = {}
    >
    > which didn't work (but frankly I didn't really expect it to.)
    > Then I tried:
    >
    > for x in ('a','b','c','d ','e','f','g'): locals()[x]={}
    >
    > which did what I wanted, in the interpreter. When I put it inside a function,
    > it doesn't seem to work. If I print locals() from inside the function, I can
    > see them, and they appear to be fine, but the first time I try to access one
    > of them I get a "NameError: global name 'a' is not defined"
    >
    > Now obviously I could easily avoid this problem by just initializing each
    > dictionary, but is there something wrong about my understanding of locals,
    > that my function isn't behaving the way I expect?
    >
    >
    >
    >[color=green]
    >>-----Original Message-----
    >>From: python-list-bounces+james.f rohnhofer=csfb. com@python.org
    >>[mailto:python-list-bounces+james.f rohnhofer=csfb. com@python.org]On
    >>Behalf Of Dennis Lee Bieber
    >>Sent: Tuesday, November 09, 2004 10:31 AM
    >>To: python-list@python.org
    >>Subject: Re: Determining combination of bits
    >>
    >>
    >>On Mon, 8 Nov 2004 21:18:36 -0800, "news.west.cox. net"
    >><sean.berry2@ cox.net> declaimed the following in comp.lang.pytho n:
    >>
    >>[color=darkred]
    >>>>Note: 2^1 = 2, so your dictionary is already in error...
    >>>>
    >>>
    >>>The dictionary was filled with arbitrary values, not
    >>>{ x : 2^x } values like you might have thought.[/color]
    >>
    >> Well, you had stated "powers of two"... If all you wanted is a
    >>bit mapping you could probably drop the dictionary and just use a list
    >>of the values, indexed by the bit position, and my first attempt
    >>logic...
    >>
    >>[color=darkred]
    >>>It is actually more like {1:123, 2:664, 4:323, 8:990, 16:221... etc}
    >>>
    >>>[/color]
    >>
    >>CheckBoxes = [ "FirstChoic e",
    >> "SecondChoi ce",
    >> "ThirdChoic e",
    >> "FourthChoi ce",
    >> "FifthChoic e",
    >> "SixthChoic e" ]
    >>
    >>
    >>for num in [22, 25, 9]:
    >> bit = 0
    >> while num:
    >> if num & 1:
    >> print CheckBoxes[bit],
    >> bit = bit + 1
    >> num = num >> 1
    >> print
    >>
    >>SecondChoic e ThirdChoice FifthChoice
    >>FirstChoice FourthChoice FifthChoice
    >>FirstChoice FourthChoice
    >>
    >>where "num" is the sum of the checkbox index values (or whatever
    >>selection mechanism is used), assuming /they/ were set up in 2^(n+1)
    >>scheme (n = bit position, starting with 0)...
    >>
    >>--[color=darkred]
    >> > =============== =============== =============== =============== == <
    >> > wlfraed@ix.netc om.com | Wulfraed Dennis Lee Bieber KD6MOG <
    >> > wulfraed@dm.net | Bestiaria Support Staff <
    >> > =============== =============== =============== =============== == <
    >> > Home Page: <http://www.dm.net/~wulfraed/> <
    >> > Overflow Page: <http://wlfraed.home.ne tcom.com/> <[/color]
    >>--
    >>http://mail.python.org/mailman/listinfo/python-list
    >>[/color]
    >
    >
    > =============== =============== =============== =============== =============== ===
    > This message is for the sole use of the intended recipient. If you received
    > this message in error please delete it and notify us. If this message was
    > misdirected, CSFB does not waive any confidentiality or privilege. CSFB
    > retains and monitors electronic communications sent through its network.
    > Instructions transmitted over this system are not binding on CSFB until they
    > are confirmed by us. Message transmission is not guaranteed to be secure.
    > =============== =============== =============== =============== =============== ===
    >[/color]

    Comment

    • Raymond Hettinger

      #3
      Re: Concise idiom to initialize dictionaries

      [Frohnhofer, James][color=blue]
      > My initial problem was to initialize a bunch of dictionaries at the start of a
      > function.
      >
      > I did not want to do
      > def fn():
      > a = {}
      > b = {}
      > c = {}
      > . . .
      > z = {}
      > simply because it was ugly and wasted screen space.[/color]

      Use exec().
      [color=blue][color=green][color=darkred]
      >>> for c in 'abcdefghijklmn opqrstuvwxyz':[/color][/color][/color]
      exec c + ' = {}'


      Of course, as others have pointed out, the whole idea is likely misguided and
      you would be better served with a list of unnamed dictionaries.


      Raymond Hettinger





      Comment

      • Peter Otten

        #4
        Re: Concise idiom to initialize dictionaries

        Frohnhofer, James wrote:
        [color=blue]
        > My initial problem was to initialize a bunch of dictionaries at the start
        > of a function.
        >
        > I did not want to do
        > def fn():
        > a = {}
        > b = {}
        > c = {}
        > . . .
        > z = {}
        > simply because it was ugly and wasted screen space.[/color]

        Here is a bunch of dictionaries that spring into existence by what is
        believed to be magic :-)
        [color=blue][color=green][color=darkred]
        >>> class AllDicts:[/color][/color][/color]
        .... def __getattr__(sel f, name):
        .... d = {}
        .... setattr(self, name, d)
        .... return d
        .... def __repr__(self):
        .... items = self.__dict__.i tems()
        .... items.sort()
        .... return "\n".join(map(" %s -> %r".__mod__, items))
        ....[color=blue][color=green][color=darkred]
        >>> ad = AllDicts()
        >>> ad.a[1] = 99
        >>> ad.b[2] = 42
        >>> ad.b[3] = 11
        >>> ad[/color][/color][/color]
        a -> {1: 99}
        b -> {2: 42, 3: 11}

        Peter


        Comment

        • Bengt Richter

          #5
          Re: Concise idiom to initialize dictionaries

          On Tue, 9 Nov 2004 16:40:48 -0000, "Frohnhofer , James" <james.frohnhof er@csfb.com> wrote:
          [color=blue]
          >My initial problem was to initialize a bunch of dictionaries at the start of a
          >function.
          >
          >I did not want to do
          >def fn():
          > a = {}
          > b = {}
          > c = {}
          > . . .
          > z = {}
          >simply because it was ugly and wasted screen space.
          >
          >First I tried:
          >
          > for x in (a,b,c,d,e,f,g) : x = {}
          >
          >which didn't work (but frankly I didn't really expect it to.)
          >Then I tried:
          >
          > for x in ('a','b','c','d ','e','f','g'): locals()[x]={}
          >
          >which did what I wanted, in the interpreter. When I put it inside a function,
          >it doesn't seem to work. If I print locals() from inside the function, I can
          >see them, and they appear to be fine, but the first time I try to access one
          >of them I get a "NameError: global name 'a' is not defined"
          >
          >Now obviously I could easily avoid this problem by just initializing each
          >dictionary, but is there something wrong about my understanding of locals,
          >that my function isn't behaving the way I expect?
          >[/color]
          Others explained why locals()[x] worked interactively, and not in a function,
          but if you just want a one-liner, you could just unpack a listcomp:
          [color=blue][color=green][color=darkred]
          >>> a,b,c = [{} for i in xrange(3)]
          >>> a,b,c[/color][/color][/color]
          ({}, {}, {})

          If you have single-letter names, you can avoid the count by stepping through the letters:
          [color=blue][color=green][color=darkred]
          >>> x,y,z = [{} for dont_care in 'xyz']
          >>> x,y,z[/color][/color][/color]
          ({}, {}, {})

          Or if you have a long target list and you can just type it and copy/paste it like:
          [color=blue][color=green][color=darkred]
          >>> fee,fie,fo,fum, bim,bah = [{} for ignore in 'fee,fie,fo,fum ,bim,bah'.split (',')]
          >>> fee,fie,fo,fum, bim,bah[/color][/color][/color]
          ({}, {}, {}, {}, {}, {})[color=blue][color=green][color=darkred]
          >>> map(id, (fee,fie,fo,fum ,bim,bah))[/color][/color][/color]
          [9440400, 9440976, 9438816, 9441120, 9440256, 9440544]


          The dicts are separate, as you can see:
          [color=blue][color=green][color=darkred]
          >>> id(a),id(b),id( c)[/color][/color][/color]
          (9153392, 9153248, 9439248)[color=blue][color=green][color=darkred]
          >>> a,b,c = [{i:chr(i+ord('0 '))} for i in xrange(3)]
          >>> a,b,c[/color][/color][/color]
          ({0: '0'}, {1: '1'}, {2: '2'})

          Regards,
          Bengt Richter

          Comment

          • bruno modulix

            #6
            Re: Concise idiom to initialize dictionaries

            Larry Bates a écrit :[color=blue]
            > It is almost certain that you should use either a list of dictionaries
            > or a dictionary containing other dictionaries for this. Creation of
            > 26 distinct dictionaries is almost never a good solution as it makes
            > it nearly impossible to iterate over them and would make code to
            > manipulate them unable to be generalized easily.
            >
            > Example:
            >
            > #
            > # To create a list of dictionaries
            > #
            > list_of_dicts=[]
            > for i in range(26):
            > list_of_dicts.a ppend({})
            >[/color]

            or just
            list_of_dicts = [{} for i in range(26)]

            or if you want a dict of dicts :
            dod = dict([(i, {}) for i in range(26)])

            Comment

            • Caleb Hattingh

              #7
              Re: Concise idiom to initialize dictionaries

              Peter, respect :)

              For interest sake, how would such a thing look with new-style classes? My
              (likely misinformed) impression is that __getattr__ for example, doesn't
              behave in quite the same way?

              thx
              Caleb


              On Tue, 09 Nov 2004 20:12:15 +0100, Peter Otten <__peter__@web. de> wrote:
              [color=blue]
              >
              > Here is a bunch of dictionaries that spring into existence by what is
              > believed to be magic :-)
              >[color=green][color=darkred]
              >>>> class AllDicts:[/color][/color]
              > ... def __getattr__(sel f, name):
              > ... d = {}
              > ... setattr(self, name, d)
              > ... return d
              > .. def __repr__(self):
              > ... items = self.__dict__.i tems()
              > ... items.sort()
              > ... return "\n".join(map(" %s -> %r".__mod__, items))
              > ...[color=green][color=darkred]
              >>>> ad = AllDicts()
              >>>> ad.a[1] = 99
              >>>> ad.b[2] = 42
              >>>> ad.b[3] = 11
              >>>> ad[/color][/color]
              > a -> {1: 99}
              > b -> {2: 42, 3: 11}
              >
              > Peter
              >[/color]

              Comment

              • Steven Bethard

                #8
                Re: Concise idiom to initialize dictionaries

                Caleb Hattingh <caleb1 <at> telkomsa.net> writes:[color=blue]
                >
                > For interest sake, how would such a thing look with new-style classes? My
                > (likely misinformed) impression is that __getattr__ for example, doesn't
                > behave in quite the same way?[/color]

                Just the same[1] =)
                [color=blue][color=green][color=darkred]
                >>> class AllDicts(object ):[/color][/color][/color]
                .... def __getattr__(sel f, name):
                .... d = {}
                .... setattr(self, name, d)
                .... return d
                .... def __repr__(self):
                .... items = self.__dict__.i tems()
                .... items.sort()
                .... return '\n'.join(['%s -> %r' % item for item in items])
                ....[color=blue][color=green][color=darkred]
                >>> ad = AllDicts()
                >>> ad.a[1] = 99
                >>> ad.b[2] = 42
                >>> ad.b[3] = 11
                >>> ad[/color][/color][/color]
                a -> {1: 99}
                b -> {2: 42, 3: 11}[color=blue][color=green][color=darkred]
                >>>[/color][/color][/color]

                I believe that __getattr__ works just the same (but to check for yourself, see
                http://docs.python.org/ref/attribute-access.html). I think what you're thinking
                of is __getattribute_ _ which new-style classes offer *in addition* to
                __getattr__. While __getattr__ is called only if an attribute is not found,
                __getattribute_ _ is called unconditionally for every attribute access.

                Steve

                [1] modulo my preference for list comprehensions/generator expressions instead
                of map

                Comment

                • Caleb Hattingh

                  #9
                  Re: Concise idiom to initialize dictionaries

                  Steve,

                  Not only did you answer my silly question, but also the question I
                  actually wanted to ask ...__getattribu te__ is what I was thinking of.

                  thats cool :)
                  thx
                  Caleb

                  On Thu, 11 Nov 2004 20:30:18 +0000 (UTC), Steven Bethard
                  <steven.bethard @gmail.com> wrote:
                  [color=blue]
                  > Caleb Hattingh <caleb1 <at> telkomsa.net> writes:[color=green]
                  >>
                  >> For interest sake, how would such a thing look with new-style classes?
                  >> My
                  >> (likely misinformed) impression is that __getattr__ for example, doesn't
                  >> behave in quite the same way?[/color]
                  >
                  > Just the same[1] =)
                  >[color=green][color=darkred]
                  >>>> class AllDicts(object ):[/color][/color]
                  > ... def __getattr__(sel f, name):
                  > ... d = {}
                  > ... setattr(self, name, d)
                  > ... return d
                  > ... def __repr__(self):
                  > ... items = self.__dict__.i tems()
                  > ... items.sort()
                  > ... return '\n'.join(['%s -> %r' % item for item in items])
                  > ...[color=green][color=darkred]
                  >>>> ad = AllDicts()
                  >>>> ad.a[1] = 99
                  >>>> ad.b[2] = 42
                  >>>> ad.b[3] = 11
                  >>>> ad[/color][/color]
                  > a -> {1: 99}
                  > b -> {2: 42, 3: 11}[color=green][color=darkred]
                  >>>>[/color][/color]
                  >
                  > I believe that __getattr__ works just the same (but to check for
                  > yourself, see
                  > http://docs.python.org/ref/attribute-access.html). I think what you're
                  > thinking
                  > of is __getattribute_ _ which new-style classes offer *in addition* to
                  > __getattr__. While __getattr__ is called only if an attribute is not
                  > found,
                  > __getattribute_ _ is called unconditionally for every attribute access.
                  >
                  > Steve
                  >
                  > [1] modulo my preference for list comprehensions/generator expressions
                  > instead
                  > of map
                  >[/color]

                  Comment

                  Working...