将* arg放在可以排序的元组中的正确方法是什么?

时间:2011-09-15 07:33:08

标签: python sorting dictionary tuples

我想要一个dict或tuple,我可以根据我用作* arg的参数的对象的属性进行排序。我一直试图做的方式只是给了我属性错误,这让我相信我做的很奇怪。

def function(*arg):
    items = {}
    for thing in arg:
        items.update({thing.name:thing})


    while True:
        for thing in items:
        ## lots of other code here, basically just a game loop.
        ## Problem is that the 'turn order' is based on whatever
        ## Python decides the order of arguments is inside "items".
        ## I'd like to be able to sort the dict based on each object's
        ## attributes (ie, highest 'thing.speed' goes first in the while loop)

问题是当我尝试根据我放入function()的对象的属性对“items”进行排序时,它给了我“AttributeError:'str'对象没有属性'attribute'”。这让我相信我要么以糟糕的方式拆包* arg,要么我试图以错误的方式做事。

while True:
    for thing in sorted(items, key=attrgetter('attribute')):

...也不起作用,一直告诉我,我正试图操纵'str'对象。我在这做什么?

3 个答案:

答案 0 :(得分:1)

arg已经 一个tuple您可以按每个项目的属性进行排序:

def function(*args):
    for thing in sorted(args, key=attrgetter('attribute')):

当您dict迭代sorted时,您只需获取密钥,而不是值。因此,如果您想使用dict,则需要执行以下操作:

def function(*args):
    # or use a dict comprehension on 2.7+ 
    items = dict((thing.name, thing) for thing in args)

    # or just items.values on 3+
    for thing in sorted(items.itervalues(), key=attrgetter('attribute')):

实际按属性对args进行排序。如果您希望dict的密钥也可用(此处不需要,因为密钥也是项目的属性),请使用以下内容:

for name, thing in sorted(items.iteritems(), key=lambda item: item[1].attribute):

答案 1 :(得分:0)

你的items是一个字典,你不能正确排序字典。当您尝试将其用作可迭代时,它会以静默方式返回其键列表,这是一个字符串列表。创建词典后,您不会使用arg

如果您不需要dict查找,只需遍历它,就可以将dict替换为2元组列表(thing.name,thing),按任意属性对其进行排序并迭代它。如果你真的想要dict查找和排序,你也可以使用Python 2.7中的collections.OrderedDict(它作为早期版本的单独ordereddict包存在)。

答案 2 :(得分:0)

{edit}感谢agf,我理解了这个问题。所以,我在下面写的内容本身就是一个很好的答案,但是当与上述问题相关时却没有...我将它放在这里以供追踪。


寻找答案,我可能还没有理解这个问题。但这是我的理解:因为args是你赋予函数的参数元组,所以这些参数都不是具有name属性的对象。但是,查看您报告的错误,您将提供字符串参数。

也许一些插图可以帮助我的描述:

>>> # defining a function using name attribute
>>> def f(*args):
...      for arg in args:
...           print arg.name
>>> # defining an object with a name attribute
>>> class o(object):
...     def __init__(self, name):
...          self.name = name
>>> # now applying the function on the previous object, and on a string
>>> f( o('arg 1'), 'arg 2' )
arg 1

Traceback (most recent call last):
  File "<pyshell#9>", line 1, in <module>
    f(o('arg 1'), 'ets')
  File "<pyshell#3>", line 3, in f
    print arg.name
AttributeError: 'str' object has no attribute 'name'

这是失败的,因为字符串没有这样的属性。

对我而言,在您的代码中,存在一个错误:您尝试在输入中使用属性name,而无需验证它们是否具有此类属性。也许您应首先使用hasattr进行测试:

>>> if hasattr(arg, 'name'):
...     print arg.name
... else:
...     print arg

或对输入进行一些检查,以验证它是否是已知具有所请求属性的给定类的实例。