Как правильно поместить * arg в кортеж, который можно отсортировать? - PullRequest
0 голосов
/ 15 сентября 2011

Я хочу сортировку или кортеж, которые я могу сортировать на основе атрибутов объектов, которые я использую в качестве аргументов для * arg. То, как я пытался это сделать, просто дает мне AttributeErrors, что наводит меня на мысль, что я делаю это странно.

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)

Проблема в том, что когда я пытаюсь отсортировать «элементы» на основе атрибута объектов, которые я поместил в функцию (), он выдает мне «AttributeError: у объекта 'str' нет атрибута" атрибут "". Это заставляет меня поверить, что я либо распаковываю * arg паршивым способом, либо пытаюсь сделать что-то неправильно.

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

... тоже не работает, постоянно говорит мне, что я пытаюсь манипулировать объектом 'str'. Что я здесь не делаю?

Ответы [ 3 ]

1 голос
/ 15 сентября 2011

arg уже равно a 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')):

, чтобы фактически отсортировать аргументы по атрибуту.Если вы хотите, чтобы ключи dict также были доступны (здесь не обязательно, поскольку ключ также является атрибутом элемента), используйте что-то вроде:

for name, thing in sorted(items.iteritems(), key=lambda item: item[1].attribute):
0 голосов
/ 15 сентября 2011

{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'

Это ошибка, поскольку строки не имеют такого атрибута.1011 *

Для меня в вашем коде есть ошибка: вы пытаетесь использовать атрибут name на своих входах, даже не проверяя, имеют ли они такой атрибут.Возможно, вам следует сначала проверить с помощью hasattr:

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

или с некоторой проверкой входных данных, чтобы убедиться, что это экземпляр заданного класса, у которого, как известно, есть запрошенный атрибут.

0 голосов
/ 15 сентября 2011

Ваш items является диктатом, вы не можете правильно отсортировать диктовку. Когда вы пытаетесь использовать его как итеративный, он молча возвращает свой список ключей, который представляет собой список строк. И вы не используете свой arg после создания диктата.

Если вам не нужен поиск dict, так как вы просто просматриваете его, вы можете заменить dict списком из двух кортежей (thing.name, thing), отсортировать его по любому атрибуту и ​​выполнить итерацию по нему. Вы также можете использовать collections.OrderedDict из Python 2.7 (он существует как отдельный пакет ordereddict для более ранних версий), если вы действительно хотите как искать, так и упорядочить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...