views:

62

answers:

3

What I'm trying to do is get 3 values from a key into separate variables. Currently I'm doing it like this:

for key in names:
   posX = names[key][0]
   posY = names[key][1]
   posZ = names[key][2]

This doesn't seem very intuitive to me even though it works. I've also tried doing this:

for key, value in names:
   location = value

Unfortunately, this gives me a single object (which is what I expected), but I need the individual values assigned to the key. Thanks and apologize for my newness to Python.

Update Apologies for not specifying where I was getting my values from. Here is how I'm doing it for the first example.

names = {}

for name in objectNames:
    cmds.select(name)
    location = cmds.xform(q=True, ws=True, t=True)
    names[name] = location
+1  A: 

If you don't mind an external dependency, you could include Werkzeug's MultiDict:

A MultiDict is a dictionary subclass customized to deal with multiple values for the same key which is for example used by the parsing functions in the wrappers.

>>> d = MultiDict([('a', 'b'), ('a', 'c')])
>>> d
MultiDict([('a', 'b'), ('a', 'c')])
>>> d['a']
'b'
>>> d.getlist('a')
['b', 'c']
>>> 'a' in d
True

Another way to store multiple values for a key is to use a container type, like a list, a set or a tuple.

The MYYN
I don't mind external dependencies at all, so I'll give this a whirl to see if it's quicker or not.
ArrantSquid
+5  A: 

It's not unintuitive at all.

The only way to store "multiple values" for a given key in a dictionary is to store some sort of container object as the value, such as a list or tuple. You can access a list or tuple by subscripting it, as you do in your first example.

The only problem with your example is that it's the ugly and inconvenient way to access such a container when it's being used in this way. Try it like this, and you'll probably be much happier:

>>> alist = [1, 2, 3]
>>> one, two, three = alist
>>> one
1
>>> two
2
>>> three
3
>>> 

Thus your second example could instead be:

for key, value in names.items():
    posX, posY, posZ = value

As FabienAndre points out in a comment below, there's also the more convenient syntax I'd entirely forgotten about, for key,(posX,posY,posZ) in names.items():.

You don't specify where you're getting these values from, but if they're coming from code you have control over, and you can depend on using Python 2.6 or later, you might also look into named tuples. Then you could provide a named tuple as the dict value, and use the syntax pos.x, pos.y, etc. to access the values:

for name, pos in names.items():
    doSomethingWith(pos.x)
    doSomethingElseWith(pos.x, pos.y, pos.z)
Nicholas Knight
I would also mention `for key,(posX,posY,posZ) in names.items():`
FabienAndre
I attempted to use your method, but kept getting Error: too many values to unpack. However, when I used your second example from FabienAndre, it worked perfectly. I think the first example didn't work because of how I'm getting my data in Maya, but I could be entirely wrong. Thanks to both of you!
ArrantSquid
@Arrant: You probably caught my first method before I added .items() to it. I'm always forgetting that for roughly the same reason I'm always forgetting Fabien's syntax, my brain tends to forget "implicit"-ish things. :)
Nicholas Knight
Yes I did and it's something that I seem to forget a lot as well - albeit I am much newer to this than you are so I forget a multitude of things. :) After changing it, I still seemed to have issues with it, but I believe it's because I'm cycling through a list. Not sure, but I've tried using the .append to no avail. :( However, the other example still works well and is explicit about what I'm trying to get, so I like it. :) Thanks again for the help! Much appreciated.
ArrantSquid
+1  A: 

Looking at your code, working with position/location variables, you could also unify the X, Y and Z position into a common type, for example using named tuples:

from collections import namedtuple

Position = namedtuple("Position", "x, y, z")

locations = {
    "chair": Position(1, 2, 5.3),
    "table": Position(5, 3.732, 6),
    "lamp": Position(4.4, 7.2, 2)
}

print "Chair X location: ", locations["chair"].x

Just a suggestion, though.

Jim Brissom
I hadn't thought of doing something like this, but I may use that in other parts of my current code, since this seems a very good way to split things up, while still making sense.
ArrantSquid