在Python中排序对象

3 投票
3 回答
553 浏览
提问于 2025-04-15 22:12

我想根据对象的某个属性来排序。目前,我是这样做的:

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[chosenCar]' 这个属性。

问题是,我想用来排序的属性在一个字典里。例如,utility 属性的格式是:

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

我想用 operator.attrgetter() 根据 chosenCar 的 utility 来排序。我该怎么做呢?

提前谢谢你。

3 个回答

1
  • 绝对不要仅仅因为你看过的某些东西就去优化代码。随便在代码里改来改去,试图让它变得更快,这并不是一个有效的优化方法。

  • 如果你想让代码更好,这里有一些步骤可以遵循。

    1. 首先,不要优化。很多时候这只是浪费时间。
    2. 先写一个能正常运行并且可以测试的程序。
    3. 确定性能指标——你需要能回答“这段代码快不快?”
    4. 意识到你的代码可能已经足够快了。
    5. 如果你不能确定第(4)步,使用工具分析你的代码,看看它在哪些地方花了时间。在Python中,你可以使用http://docs.python.org/library/profile.html来做到这一点。瓶颈往往出现在意想不到的地方,这个工具会告诉你哪些地方需要你去努力优化。
    6. 检查那些耗时的代码,看看是否有算法上的问题。有时候这个问题出现在你当前的代码中,但往往在更高的层次上也会出现。改善你的算法几乎总是能带来最大的速度提升。
    7. 如果你无法改善算法,可以测试不同的代码片段,看看它们的表现如何。使用http://docs.python.org/library/timeit.html来测试代码片段(这比人们想象的要复杂,所以要小心),然后重新进行性能测试和分析。

      虽然可能会想在一开始就进行这个步骤,但这通常不会有好结果。你需要确保你所优化的内容是有意义的。

    希望这些能帮助你理解如何加速代码(以及什么时候不需要去做)。我见过很多人试图用一些经验法则来替换代码,但我没有见过那些人写出优秀、快速的软件。优化必须是科学的,结合理论(比如计算机科学的知识)和实验(比如时间测试)。

  • 在这个具体的例子中,我敢打赌SilentGhost的代码最终会比你的慢。当然我不能确定,但你也不能,除非你去测试一下。

    (而且我觉得你不需要去测试,我认为你应该选择最清晰的方法,也就是你最初的那个。)

2

不,attrgetter 并不会比 lambda 更快,它其实只是另一种做同样事情的方法。

你可能是被建议使用 key 而不是 cmp 给搞混了,确实 key 会快很多,但你已经在使用 key 了。

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 模块来测试你自己数据的两种方法的性能。

撰写回答