Сортировка объектов в Python - PullRequest
3 голосов
/ 30 апреля 2010

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

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)

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

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

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

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

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

Ответы [ 3 ]

2 голосов
/ 30 апреля 2010

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

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

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

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

    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 в конечном итоге будет медленнее, чем ваш. Я, конечно, не знаю наверняка, но и вы тоже, если вы не примете это время.

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

1 голос
/ 30 апреля 2010

для доступа к 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 для проверки производительности обоих подходов для ваших собственных данных.

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