2010-04-30 6 views
3

Я хочу отсортировать объекты по одному из своих атрибутов. В настоящее время, я делаю это следующим образомСортировка объектов в Python

USpeople.sort(key=lambda person: person.utility[chosenCar],reverse=True) 

Это прекрасно работает, но я читал, что с помощью operator.attrgetter() может быть более быстрым способом для достижения такого рода. Во-первых, это правильно? Предполагая, что это правильно, как я могу использовать operator.attrgetter() для достижения такого рода?

Я попытался,

keyFunc=operator.attrgetter('utility[chosenCar]') 
USpeople.sort(key=keyFunc,reverse=True) 

Однако я получаю сообщение об ошибке сказав, что нет атрибута 'полезности [chosenCar].

Проблема в том, что атрибут, по которому я хочу сортировать, находится в словаре. Например, атрибут утилита в следующем виде:

utility={chosenCar:25000,anotherCar:24000,yetAnotherCar:24500} 

Я хочу, чтобы отсортировать по полезности chosenCar с помощью operator.attrgetter(). Как я могу это сделать?

Заранее спасибо.

ответ

1

для доступа chosenCar элемента, который должен был бы использовать:

>>> P.utility={'chosenCar':25000,'anotherCar':24000,'yetAnotherCar':24500} 
>>> operator.itemgetter('chosenCar')(operator.attrgetter('utility')(P)) 
25000 

для функции key вы должны сделать следующее:

>>> def keyfunc(P): 
    util = operator.attrgetter('utility')(P) 
    return operator.itemgetter('chosenCar')(util) 

>>> USpeople.sort(key=keyfunc,reverse=True) 

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

+0

Спасибо за указание на то, что скорость не увеличится , Тем не менее, я хотел бы понять ваше решение для использования operator.attrgetter для будущего. Объект, который у меня есть, находится в списке. Например, people = [P1, P2, P3, P4] , где P1, P2, P3, P4 являются лицами. Я хочу отсортировать это с помощью attrgetter. Что я пишу вместо (P), которое у вас есть во второй строке. Спасибо. – Curious2learn

+0

@ Curious: обновлено – SilentGhost

+1

Конечно, 'operator.attrgetter ('utility') (P)' - просто глупый способ записи 'P.utility'. Причина использования 'operator.attrgetter' и' operator.itemgetter' заключается в том, когда вы можете использовать их * напрямую *. Если вы собираетесь написать свою собственную ключевую функцию, это будет просто «вернуть P.utility ['selectedCar]], точно так же, как и лямбда. –

2

Нет, attrgetter не будет быстрее, чем лямбда - это действительно просто другой способ сделать то же самое.

Возможно, вы были смущены рекомендацией использовать key вместо cmp, что действительно значительно быстрее, но вы уже это делаете.

+0

Дани, спасибо за разъяснение. – Curious2learn

+0

'attrgetter' быстрее, чем лямбда, поскольку он реализован в C. Разница составляет лишь около 15%, хотя, по моим результатам. – interjay

1
  • Никогда, никогда, никогда не оптимизируют на основе что вы прочитали. Переход к вашему коду и внесение случайных изменений из того, что у вас есть на то, что, по вашему мнению, должно быть быстрее, - не рабочая стратегия оптимизации.

  • Вот как вы оптимизируете, если хотите улучшить свой код.

    1. Не делайте этого. Это часто пустая трата времени.
    2. Сделать рабочую, проверяемую программу.
    3. Определите показатели производительности - сможете ответить «Является ли этот код достаточно быстрым?»
    4. Поймите, что ваш код уже достаточно быстро.
    5. Если вы не смогли выполнить шаг (4), прокомментируйте свой код для реалистичного ввода, чтобы определить, где он проводит свое время. В Python вы можете использовать http://docs.python.org/library/profile.html для этого. Узкие места происходят в неожиданных местах, и это скажет вам, где вы на самом деле должны прилагать усилия.
    6. Изучите долговременный код алгоритмической субоптимальности. Это иногда происходит на том уровне, который вы есть, но часто происходит и несколько уровней. Улучшение вашего алгоритма почти всегда будет самым большим шансом на ускорение.
    7. Если вы не можете улучшить свой алгоритм, проверьте различные фрагменты кода, которые делают то же самое, и посмотрите, как они работают. Используйте http://docs.python.org/library/timeit.html для тестирования фрагментов (это сложнее получить, чем люди понимают, поэтому будьте осторожны) и повторите тесты производительности и профиль.

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

    Я надеюсь, что это дает некоторое представление о том, как ускорить ваш код (и если не беспокоить). Я видел, как многие люди пытаются заменить случайный код оптимизацией правил большого пальца, но я не видел тех людей, которые производят отличное, быстрое программное обеспечение. Оптимизация должна проводиться с научной точки зрения, используя теорию (например, информатику в 6) и эксперименты (например, время в 7).

  • В этом конкретном случае я бы поставил деньги на то, что код SilentGhost в конечном счете медленнее вашего. Я, конечно, не знаю точно, но вы тоже, если не хотите.

    (И я не думаю, что вы должны беспокоиться Timing, я думаю, вы должны пойти с ясным подходом, оригинал один.)

+0

Спасибо за ваш комментарий. Я профилировал свой код после того, как задал вопрос и нашел функцию, которая занимает большую часть времени. Я собираюсь подумать, могу ли я использовать лучший алгоритм. Если я не могу, я вернусь к stackoverflow для любых идей. – Curious2learn

Смежные вопросы