Python字典中的一个键有多个值

7
我要做的是将一个键中的三个值分别赋给不同的变量。目前我是这样做的:
for key in names:
   posX = names[key][0]
   posY = names[key][1]
   posZ = names[key][2]

这个方法虽然有效,但对我来说并不太直观。我也尝试过这样做:
for key, value in names:
   location = value

很不幸,这给了我一个单一的对象(这是我预期的),但我需要将各个值分配给键。感谢并为我对Python的新鲜感道歉。
更新 很抱歉没有说明我从哪里获取我的值。以下是我在第一个示例中执行此操作的方式。
names = {}

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

这就是我的最终尝试的结果:names = {}for name in objectNames: cmds.select(name) location = cmds.xform(q=True, ws=True, t=True) names[name] = locationfor key, (posX, posY, posZ) in names.items(): jointPosX = posX jointPosY = posY jointPosZ = posZ - John P
3个回答

11

这一点并不难理解。

在字典中存储给定键的“多个值”的唯一方法是将某种容器对象(例如列表或元组)作为值存储。您可以通过下标访问列表或元组,就像在第一个示例中所做的那样。

您的示例的唯一问题是当以这种方式使用容器时,这是一个丑陋和不方便的访问方式。尝试像这样使用,您可能会更加满意:

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

因此,你的第二个例子可以改为:

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

正如FabienAndre在下面的一条评论中指出的那样,还有更方便的语法我完全忘记了,for key,(posX,posY,posZ) in names.items():

您没有指定这些值来自何处,但如果它们来自您可以控制的代码,并且您可以依赖于使用Python 2.6或更高版本,则还可以查看命名元组。然后,您可以提供一个命名元组作为字典值,并使用语法pos.xpos.y等来访问值:

for name, pos in names.items():
    doSomethingWith(pos.x)
    doSomethingElseWith(pos.x, pos.y, pos.z)

2
我还想提一下 for key,(posX,posY,posZ) in names.items(): - FabienAndre
我尝试使用您的方法,但一直收到“错误:值过多无法解包”的提示。然而,当我使用FabienAndre的第二个示例时,它完美地工作了。我认为第一个示例之所以不起作用是因为我在Maya中获取数据的方式,但我可能完全错了。感谢你们两个! - John P
@Arrant:你可能在我添加.items()之前就捕捉到了我的第一种方法。我总是忘记大致相同的原因,就像我总是忘记法比安的语法一样,我的大脑倾向于忘记“隐式”这样的东西。 :) - Nicholas Knight
是的,我做过,而且这似乎也是我经常忘记的事情 - 尽管我在这方面比你新得多,所以我会忘记很多东西。:) 改变了它之后,我似乎仍然有一些问题,但我相信这是因为我正在遍历一个列表。不确定,但我已经尝试过使用.append方法,但没有成功。:( 然而,另一个例子仍然运行良好,并且明确说明了我的意图,所以我喜欢它。:) 再次感谢帮助!非常感激。 - John P

2
如果你不介意使用外部依赖,你可以包含Werkzeug的MultiDict

MultiDict是一个字典子类,专门用于处理同一键的多个值,例如由包装器中的解析函数使用。

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

一种存储一个键的多个值的方法是使用容器类型,例如listsettuple

我并不介意外部依赖,所以我会试一试看这样做是否更快。 - John P

2

看着你的代码,使用位置/坐标变量,你也可以将X、Y和Z位置统一到一个公共类型中,例如使用命名元组:

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

只是一个建议而已。


我之前没有想过这样做,但是我可能会在当前代码的其他部分使用它,因为这似乎是一个非常好的分割代码的方法,同时仍然有意义。 - John P
如何动态填充对象位置? - Punit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接