By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,905 Members | 879 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,905 IT Pros & Developers. It's quick & easy.

Concise idiom to initialize dictionaries

P: n/a
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?
-----Original Message-----
From: py*******************************************@pyth on.org
[mailto:py***************************************** **@python.org]On
Behalf Of Dennis Lee Bieber
Sent: Tuesday, November 09, 2004 10:31 AM
To: py*********@python.org
Subject: Re: Determining combination of bits
On Mon, 8 Nov 2004 21:18:36 -0800, "news.west.cox.net"
<se*********@cox.net> declaimed the following in comp.lang.python:
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.


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...

It is actually more like {1:123, 2:664, 4:323, 8:990, 16:221... etc}


CheckBoxes = [ "FirstChoice",
"SecondChoice",
"ThirdChoice",
"FourthChoice",
"FifthChoice",
"SixthChoice" ]
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)...

--
> ================================================== ============ <
> wl*****@ix.netcom.com | Wulfraed Dennis Lee Bieber KD6MOG <
> wu******@dm.net | Bestiaria Support Staff <
> ================================================== ============ <
> Home Page: <http://www.dm.net/~wulfraed/> <
> Overflow Page: <http://wlfraed.home.netcom.com/> <

--
http://mail.python.org/mailman/listinfo/python-list


================================================== ============================
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.
================================================== ============================

Jul 18 '05 #1
Share this Question
Share on Google+
8 Replies


P: n/a
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.append({})

#
# 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_lowercase:
dict_of_dicts[letter]={}

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

Larry Bates
Frohnhofer, James wrote:
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?

-----Original Message-----
From: py*******************************************@pyth on.org
[mailto:py***************************************** **@python.org]On
Behalf Of Dennis Lee Bieber
Sent: Tuesday, November 09, 2004 10:31 AM
To: py*********@python.org
Subject: Re: Determining combination of bits
On Mon, 8 Nov 2004 21:18:36 -0800, "news.west.cox.net"
<se*********@cox.net> declaimed the following in comp.lang.python:

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.


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...

It is actually more like {1:123, 2:664, 4:323, 8:990, 16:221... etc}


CheckBoxes = [ "FirstChoice",
"SecondChoice",
"ThirdChoice",
"FourthChoice",
"FifthChoice",
"SixthChoice" ]
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)...

--
> ================================================== ============ <
> wl*****@ix.netcom.com | Wulfraed Dennis Lee Bieber KD6MOG <
> wu******@dm.net | Bestiaria Support Staff <
> ================================================== ============ <
> Home Page: <http://www.dm.net/~wulfraed/> <
> Overflow Page: <http://wlfraed.home.netcom.com/> <

--
http://mail.python.org/mailman/listinfo/python-list

================================================== ============================
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.
================================================== ============================

Jul 18 '05 #2

P: n/a
[Frohnhofer, James]
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.


Use exec().
for c in 'abcdefghijklmnopqrstuvwxyz':

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

Jul 18 '05 #3

P: n/a
Frohnhofer, James wrote:
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.


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

a -> {1: 99}
b -> {2: 42, 3: 11}

Peter
Jul 18 '05 #4

P: n/a
On Tue, 9 Nov 2004 16:40:48 -0000, "Frohnhofer, James" <ja**************@csfb.com> wrote:
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?

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:
a,b,c = [{} for i in xrange(3)]
a,b,c ({}, {}, {})

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

Or if you have a long target list and you can just type it and copy/paste it like:
fee,fie,fo,fum,bim,bah = [{} for ignore in 'fee,fie,fo,fum,bim,bah'.split(',')]
fee,fie,fo,fum,bim,bah ({}, {}, {}, {}, {}, {}) map(id, (fee,fie,fo,fum,bim,bah)) [9440400, 9440976, 9438816, 9441120, 9440256, 9440544]
The dicts are separate, as you can see:
id(a),id(b),id(c) (9153392, 9153248, 9439248) a,b,c = [{i:chr(i+ord('0'))} for i in xrange(3)]
a,b,c

({0: '0'}, {1: '1'}, {2: '2'})

Regards,
Bengt Richter
Jul 18 '05 #5

P: n/a
Larry Bates a écrit :
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.append({})


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)])
Jul 18 '05 #6

P: n/a
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 <__*******@web.de> wrote:

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

a -> {1: 99}
b -> {2: 42, 3: 11}

Peter


Jul 18 '05 #7

P: n/a
Caleb Hattingh <caleb1 <at> telkomsa.net> writes:

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?


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


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

Jul 18 '05 #8

P: n/a
Steve,

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

thats cool :)
thx
Caleb

On Thu, 11 Nov 2004 20:30:18 +0000 (UTC), Steven Bethard
<st************@gmail.com> wrote:
Caleb Hattingh <caleb1 <at> telkomsa.net> writes:

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?


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


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


Jul 18 '05 #9

This discussion thread is closed

Replies have been disabled for this discussion.