Creating variables from dicts

V

vsoler

Hi,

I have two dicts

n={'a', 'm', 'p'}
v={1,3,7}

and I'd like to have

a=1
m=3
p=7

that is, creating some variables.

How can I do this?
 
A

Arnaud Delobelle

vsoler said:
Hi,

I have two dicts

n={'a', 'm', 'p'}
v={1,3,7}

These are sets, not dicts.
and I'd like to have

a=1
m=3
p=7

As sets are unordered, you may as well have

a = 3
m = 7
p = 1

or any other permutation. You need some sequences instead. E.g.

n = ['a', 'm', 'p']
v = (1, 3, 7)

Then you can do:

for name, value in zip(n, v):
globals()[name] = value

After this the names, 'a', 'm' and 'p' will be bound to the values you
want in the global namespace. However, it is almost always a bad idea
to do this. Can you explain why you need to do this?
 
M

MRAB

vsoler said:
Hi,

I have two dicts

n={'a', 'm', 'p'}
v={1,3,7}
Those aren't dicts, they're sets.
and I'd like to have

a=1
m=3
p=7

that is, creating some variables.

How can I do this?

The real question is not how, but why?

Anyway, assuming you want them to be global variables:

globals().update(dict(zip(n, v)))

On my machine the variables didn't get the correct values because, as I
said, 'n' and 'v' are sets, so the order of the members is arbitrary.
 
L

Luis M. González

Hi,

I have two dicts

n={'a', 'm', 'p'}
v={1,3,7}

and I'd like to have

a=1
m=3
p=7

that is, creating some variables.

How can I do this?

You are probably coming from another language and you're not used to
python's data structures.
If you want a list of items, you use tuples or lists. Examples:

('a', 'm', 'p') ---> this is a tuple, and it's made with
parenthesis ()
['a', 'm', 'p'] ---> this is a list, and it's made with brackets
[]

Check the documentation to see the difference between tuples and
lists.
For now, lets just use lists and forget about tuples...
Now if you want a sequence of items ordered a key + value pairs, use a
dictionary, as follows:

{'name': 'joe', 'surname': 'doe', 'age': 21} ---> this is a dict,
and it's made with curly braces {}.

Curly braces are also used to create sets, but you don't need them now
(check the documentation to learn more about sets).
So going back to your question, you should have two lists, as follows:

n = ['a', 'm', 'p']
v = [1,3,7] --> note that I used brackets [], not curly
braces {}.

And now you can build a dict formed by the keys in "n" and the values
in "v":

myDict = {} --> this is an new empty dictionary
for k,v in zip(n,v):
myDict[k] = v

This results in this dictionary: {'a': 1, 'p': 7, 'm': 3}.

Hope this helps...
Luis
 
L

Luis M. González

I have two dicts
n={'a', 'm', 'p'}
v={1,3,7}
and I'd like to have

that is, creating some variables.
How can I do this?

You are probably coming from another language and you're not used to
python's data structures.
If you want a list of items, you use tuples or lists. Examples:

    ('a', 'm', 'p') ---> this is a tuple, and it's made with
parenthesis ()
    ['a', 'm', 'p'] ---> this is a list, and it's made with brackets
[]

Check the documentation to see the difference between tuples and
lists.
For now, lets just use lists and forget about tuples...
Now if you want a sequence of items ordered a key + value pairs, use a
dictionary, as follows:

    {'name': 'joe', 'surname': 'doe', 'age': 21} ---> this is a dict,
and it's made with curly braces {}.

Curly braces are also used to create sets, but you don't need them now
(check the documentation to learn more about sets).
So going back to your question, you should have two lists, as follows:

    n = ['a', 'm', 'p']
    v = [1,3,7]         --> note that I used brackets [], not curly
braces {}.

And now you can build a dict formed by the keys in "n" and the values
in "v":

    myDict = {}           --> this is an new empty dictionary
    for k,v in zip(n,v):
        myDict[k] = v

This results in this dictionary: {'a': 1, 'p': 7, 'm': 3}.

Hope this helps...
Luis

By the way, if you want the variables inside myDict to be free
variables, you have to add them to the local namespace.
The local namespace is also a dictionary "locals()".
So you can update locals as follows:

locals().update( myDictionary )

This way, all the key-value pairs inside myDict become free variables.
Wich is the same as declaring them as follows:

a = 1
p = 7

etc...

Luis
 
T

Tim Chase

Luis said:
If you want a list of items, you use tuples or lists. Examples:

('a', 'm', 'p') ---> this is a tuple, and it's made with
parenthesis ()

Actually, a tuple is made with commas...the parens are just there
to clarify the order of operations and make it easier to read :)
(1, 2, 3)

-tkc
 
S

Steven D'Aprano

By the way, if you want the variables inside myDict to be free
variables, you have to add them to the local namespace. The local
namespace is also a dictionary "locals()". So you can update locals as
follows:

locals().update( myDictionary )

No you can't. Try it inside a function.
 
L

Luis M. González

No you can't. Try it inside a function.

Sure. Inside a function I would use globals() instead.
Although I don't know if it would be a good practice...

Luis
 
S

Steven D'Aprano

Sure. Inside a function I would use globals() instead. Although I don't
know if it would be a good practice...

Er, how does using globals change the local variables?
 
S

Steven D'Aprano

Hmmm.... well, you tell me!

I'm not the one that said you can update locals! You said it. I said you
can't, because you *can't*. The docs warn that you can't change locals,
and if you try it, you will see that the docs are right.

.... x = 1
.... locals().update(x = 2)
.... print x
....
1





As I said, I don't know if this is the recomended way...

It's not recommended because it doesn't work.
 
L

Luis M. González

I'm not the one that said you can update locals! You said it. I said you
can't, because you *can't*. The docs warn that you can't change locals,
and if you try it, you will see that the docs are right.


...     x = 1
...     locals().update(x = 2)
...     print x
...


It's not recommended because it doesn't work.

I guess I have to check the docs...
Anyway, nobody wanted to update locals() from within a function here.
Doing it outside of a function seems to work.
And updating globals() works in any case, which is what the OP seems
to need. Isn't it?

Luis
 
L

Luis M. González

I guess I have to check the docs...
Anyway, nobody wanted to update locals() from within a function here.
Doing it outside of a function seems to work.
And updating globals() works in any case, which is what the OP seems
to need. Isn't it?

Luis

Alright, this is what the docs say about locals:
"Note
The built-in functions globals() and locals() return the current
global and local dictionary, respectively, which may be useful to pass
around for use as the second and third argument to exec().

Note
The default locals act as described for function locals() below:
modifications to the default locals dictionary should not be
attempted. Pass an explicit locals dictionary if you need to see
effects of the code on locals after function exec() returns."

I wonder why updating locals(), not from within a function, works (at
least in my interactive session).
And what about the trick of updating globals? Is it legal? If not, is
there any "legal" way to do what the OP needs?

Luis
 
B

Bruno Desthuilliers

Luis M. González a écrit :
You are probably coming from another language and you're not used to
python's data structures.
If you want a list of items, you use tuples or lists.

<pedantic>

If you want a list, then you use a list - not a tuple !-)
Examples:

('a', 'm', 'p') ---> this is a tuple, and it's made with
parenthesis ()

It's not the parens that "make" the tuple, it's the commas:

The only case where the parens are required is to define an empty tuple:<type 'tuple'>

</<pedantic>

Now it's most of the time a good idea to still use the parens since it
makes for more readable code (IMHO...)

(snip helpful content)
 
B

Bruno Desthuilliers

Luis M. González a écrit :
Sure. Inside a function I would use globals() instead.
Although I don't know if it would be a good practice...

It's even worse than a bad practice. Hint : why is "globals" named
"globals" and not "locals" ?
 
B

Bruno Desthuilliers

Luis M. González a écrit :
(snip)
Alright, this is what the docs say about locals:
"Note
The built-in functions globals() and locals() return the current
global and local dictionary, respectively, which may be useful to pass
around for use as the second and third argument to exec().

Note
The default locals act as described for function locals() below:
modifications to the default locals dictionary should not be
attempted. Pass an explicit locals dictionary if you need to see
effects of the code on locals after function exec() returns."

I wonder why updating locals(), not from within a function, works (at
least in my interactive session).

Because at the top level, locals and globals are the same thing.
And what about the trick of updating globals? Is it legal?

It's legal, but it's (usually) a very bad idea - at the top-level, it
harms readability, and from within a function it's doubly bad
(readibility + "globals are evil").

Now as usual with GoldenRules(tm), it's meant to be broken - once you do
know why you shouldn't _usually_ do it.


for the very same reasons global
 
L

Luis M. González

Luis M. Gonz lez a crit :
(snip)




Because at the top level, locals and globals are the same thing.


It's legal, but it's (usually) a very bad idea - at the top-level, it
harms readability, and from within a function it's doubly bad
(readibility + "globals are evil").

Now as usual with GoldenRules(tm), it's meant to be broken - once you do
know why you shouldn't _usually_ do it.

  for the very same reasons global

I still don't understand why is it a bad idea in the case of
globals().
This is the only way I know to define variables programatically in the
top-level namespace, without having to do it manually one by one.
I don't see the readability problem either.
Talking about Goldenrules(tm), what's the recomended way to do it?

Luis
 
B

Bruno Desthuilliers

Luis M. González a écrit :
I still don't understand why is it a bad idea in the case of
globals().

please not the _usually_.
This is the only way I know to define variables programatically in the
top-level namespace, without having to do it manually one by one.
I don't see the readability problem either.

# wrong.py

x = 42

def bar():
return x + 1


def test():
y = bar()
assert y==43

# snip 1kloc

def foo():
globals()[x] = 43
quux()

# snip some more core

def quux():
globals()[y] = 1138

# snip some more core

if __name__ == '__main__':
foo()


Enjoy...
Talking about Goldenrules(tm), what's the recomended way to do it?

The "recommanded way" is
1/ to avoid using globals to share state whenever possible
2/ to avoid creating globals from a function

If your problem is to conditionnaly define globals (based on environment
value or whatnot), then just write the conditional at the top level.

Now I don't say there's no legitimate use case for updating the global
namespace from within a function - just that this is a very very very
rare beast (never meet her as far as I'm concerned, and I did write some
hairy code), and even then is BadEnough(tm) to require a good documentation.

FWIW, your example seemed to be about updating the global namespace from
within a function just to have the names available in the function,
which is about the worst possible solution to the OP problem.

wrt/ the OP question, mapping a sequence of values to a sequence of
names is a legitimate concern, but you just dont need to define these
names in the local namespace to use them - just stick'em in a dict and
you're fine.
 
S

Steven D'Aprano

I wonder why updating locals(), not from within a function, works (at
least in my interactive session).

Because if you're in the global scope, locals() returns globals(), which
is a real namespace and modifying it works.

Inside a function, locals() returns a dict which is a *copy* of the
function namespace. The reason for this is that local namespaces are not
actually dicts, and you can't modify them except by actually assigning
and deleting names in code.

And what about the trick of updating globals? Is it legal? If not, is
there any "legal" way to do what the OP needs?

Yes, it is legal to modify globals(). It's just a dict, you can even do
this:
4

although that's a pretty useless trick.

But whether you should is another story. I won't say you should NEVER do
so, but it should be rare to use global variables, and even rarer to
create them programmatically. The better solution is almost always to
create your own namespace, namely a dict, and use that explicitly.
 

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,780
Messages
2,569,609
Members
45,254
Latest member
Top Crypto TwitterChannel

Latest Threads

Top