undo a dictionary

M

mmm

I found code to undo a dictionary association.

def undict(dd, name_space=globals()):
for key, value in dd.items():
exec "%s = %s" % (key, repr(value)) in name_space

So if i run

I get1 B

Here, a=1 and b='B'

This works well enough for simple tasks and I understand the role of
globals() as the default names space, but creating local variables is
a problem. Also having no output arguemtns to undict() seems
counterintuitive. Also, the function fails if the key has spaces or
operand characters (-,$,/,%). Finally I know I will have cases where
not clearing (del(a,b)) each key-value pair might create problems in a
loop.

So I wonder if anyone has more elegant code to do the task that is
basically the opposite of creating a dictionary from a set of
globally assigned variables. And for that matter a way to create a
dictionary from a set of variables (local or global). Note I am not
simply doing and undoing dict(zip(keys,values))
 
K

Kay Schluehr

I found code to undo a dictionary association.

def undict(dd, name_space=globals()):
for key, value in dd.items():
exec "%s = %s" % (key, repr(value)) in name_space

So if i run


I get>>> print A, B

1 B

Here, a=1 and b='B'

This works well enough for simple tasks and I understand the role of
globals() as the default names space, but creating local variables is
a problem.

Python is lexically scoped. You can't create locals at runtime.
Also having no output arguemtns to undict() seems
counterintuitive. Also, the function fails if the key has spaces or
operand characters (-,$,/,%).

Python names can't have punctuation with the exception of underscores.
Finally I know I will have cases where
not clearing (del(a,b)) each key-value pair might create problems in a
loop.

So I wonder if anyone has more elegant code to do the task that is
basically the opposite of creating a dictionary from a set of
globally assigned variables. And for that matter a way to create a
dictionary from a set of variables (local or global). Note I am not
simply doing and undoing dict(zip(keys,values))

May I ask what's wrong with having namespaces in a language?
 
B

bockman

I found code to undo a dictionary association.

def undict(dd, name_space=globals()):
    for key, value in dd.items():
        exec "%s = %s" % (key, repr(value)) in name_space

So if i run


I get>>> print A, B

1 B

Here,  a=1 and b='B'

This works well enough for simple tasks and I understand the role of
globals() as the default names space, but creating local variables is
a problem. Also having no output arguemtns to undict() seems
counterintuitive.  Also, the function fails if the key has spaces or
operand characters (-,$,/,%).  Finally I know I will have cases where
not clearing (del(a,b)) each key-value pair might create problems in a
loop.

So I wonder if anyone has more elegant code to do the task that is
basically the opposite of creating a dictionary from a set of
globally assigned variables.  And for that matter a way to create a
dictionary from a set of variables (local or global).  Note I am not
simply doing and  undoing dict(zip(keys,values))


Maybe you can use objects as pseudo name spaces and do sommething like
this:
def dict(self):
res = dict()
for k, v in self.__dict__.items(): res[k] = v
return res
def undict(self, dict):
for k,v in dict.items():
setattr(self, k, v )



Ciao
 
T

Terry Reedy

mmm said:
I found code to undo a dictionary association.

def undict(dd, name_space=globals()):
for key, value in dd.items():
exec "%s = %s" % (key, repr(value)) in name_space

You are not undoing anything. You are updating globals() from another
dict. But why repr(value)? Without that, globals().update(dd) would
work. In 2.6?/3.0, replace 'dd' with '{a:b for a,b in dd.items()}

dd = { 'a':1, 'b': 'B'}
globals().update({a:b for a,b in dd.items()})
print(a,b)
# 1,B
I get
1 B

Here, a=1 and b='B'

Don't fake interactive output. You would have to "print a,b". Above
gives a NameError.
This works well enough for simple tasks and I understand the role of
globals() as the default names space, but creating local variables is
a problem.

Within functions, yes. Just access the values in the dict.
> Also having no output arguemtns to undict() seems
counterintuitive.

In Python, this is standard for functions that mutate.
> Also, the function fails if the key has spaces or
operand characters (-,$,/,%).

Exec is tricky. Most people hardly ever use it.
> Finally I know I will have cases where
not clearing (del(a,b)) each key-value pair might create problems in a
loop.

You cannot mutate a dict while iterating through it.
So I wonder if anyone has more elegant code to do the task that is
basically the opposite of creating a dictionary from a set of
globally assigned variables.

See above.
And for that matter a way to create a
dictionary from a set of variables (local or global).

You have to be more specific: there are {} displays and dict(args) call
and other methods. Read the manual.

tjr
 
M

mmm

And for that matter a way to create a
You have to be more specific: there are {} displays and dict(args) call
and other methods.  Read the manual.

My desire is to take a set of data items in an alpha-numeric range and
oput them into a dictionary

i.e.,
x1=1
x2=20
x3=33

to yield the dictionary

{ 'x1':1, 'x2':20, 'x3':33 }

without having to type in as above but instead invoke a function

maybe with syntax of

dd=make_dict('x1--x99')
 
A

Alan Franzoni

mmm was kind enough to say:
My desire is to take a set of data items in an alpha-numeric range and
oput them into a dictionary

i.e.,
x1=1
x2=20
x3=33

to yield the dictionary

{ 'x1':1, 'x2':20, 'x3':33 }

without having to type in as above but instead invoke a function

maybe with syntax of

dd=make_dict('x1--x99')

you'll need to pass the locals() or globals() manually. Can't be done
(cleanly) otherwise. Check the following code:

import re

x1=1
x2=20
x3=30
q6=40

def make_dict(regex, nsmapping):
output_dict = {}
compiled_regex = re.compile(regex)
for key, value in nsmapping.items():
if compiled_regex.match(key):
output_dict[key] = value

return output_dict




d = make_dict("x[123]", locals())

print d





--
Alan Franzoni <[email protected]>
-
Remove .xyz from my email in order to contact me.
-
GPG Key Fingerprint:
5C77 9DC3 BD5B 3A28 E7BC 921A 0255 42AA FE06 8F3E
 
G

Gabriel Genellina

My desire is to take a set of data items in an alpha-numeric range and
oput them into a dictionary

i.e.,
x1=1
x2=20
x3=33

to yield the dictionary

{ 'x1':1, 'x2':20, 'x3':33 }

without having to type in as above but instead invoke a function

dict(x1=1, x2=20, x3=33) does the same thing.

Or, do you mean you already have those names and values, perhaps mixed
with a lot more names, and want to extract only those starting with "x"
and following with a number?

result = {}
for name, value in vars(): # or locals().items(), or globals().items(), or
vars(some_module)
if name[0]=='x' and name[1:].isdigit():
result[name] = value
 
C

castironpi

En Wed, 30 Jul 2008 16:14:31 -0300, mmm <[email protected]> escribi :


My desire is to take a set of data items in an alpha-numeric range and
oput them into a dictionary

to yield  the dictionary
{ 'x1':1, 'x2':20, 'x3':33 }
without having to type in as above but instead invoke a function

dict(x1=1, x2=20, x3=33) does the same thing.

Or, do you mean you already have those names and values, perhaps mixed  
with a lot more names, and want to extract only those starting with "x"  
and following with a number?

result = {}
for name, value in vars(): # or locals().items(), or globals().items(), or  
vars(some_module)
   if name[0]=='x' and name[1:].isdigit():
     result[name] = value

You can also use a blank class instance, and update its __dict__
member with the dictionary you design.
class A: pass ...
d= { 'x1': 0, 'x2': set( ) }
A.__dict__ {'__module__': '__main__', '__doc__': None}
A.__dict__.update( d )
A.__dict__ {'x2': set([]), '__module__': '__main__', 'x1': 0, '__doc__': None}
A.x1 0
A.x2 set([])

I agree that locals( ) shouldn't necessarily be read-only, and I
believe it would extend the power of Python if it weren't.
 
M

mmm

Gabriel,

I meant the latter, so this helps
Or, do you mean you already have those names and values, perhaps mixed  
with a lot more names, and want to extract only those starting with "x"  
and following with a number?

result = {}
for name, value in vars(): # or locals().items(), or globals().items(), or  
vars(some_module)
   if name[0]=='x' and name[1:].isdigit():
     result[name] = value

But I got an error with 'for name, value in vars():'
RuntimeError: dictionary changed size during iteration

I think globals() has the same problem, but globals.items() works. I
will need to read the docs to learn why '.items()' works but the
changing global dictionary problem makes sense. I assume I need to
use a non dynamic created list.

Sometimes I get the error about 'too many variables to unpack' (can
not consistently repeat the error however)

In any event, thanks for the suggestions, everyone.

Using a blank class for unpacking the dictionary makes the most sense,
for safety sake.
So you know the general issue is I want to switch between using
dictionaries for storing data items and simple variable names for
writing equations/formulas, So (a) and (b) below are preferred to (c)
for readability

(a) straight forward equation

y = b0 + b1*Age + b2*Size

(b) Class version

y = b0 + b1*x.Age + b2*x.Size

(c) Dictionary version

y = b0 + b1*dd.get('Age') + b2*dd.get('Size')
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,739
Latest member
Clint8040

Latest Threads

Top