【发布时间】:2014-04-14 13:48:51
【问题描述】:
我正在从一本书中自学 Python,但我一直在进行编程练习。练习的目的是制作一个对象列表,然后根据某些对象属性对这些对象进行排序。
我的教科书的作者说,在排序期间使用一个键为每次比较调用一个类方法会减慢大型数据集的排序时间,并且通过为每个对象调用一次类方法来构建一个“装饰”列表你建立的列表可以使后续的排序更有效率。编程问题规定,我应该创建一系列元组,而不是键,其中元组元素 0 是对象属性的字面值,元组元素 1 是对象本身。有了我的装饰列表后,我可以使用内置的列表排序方法(例如“sorted()”或“.sort()”等)将它们全部排序。
当两个对象具有相同的排序属性值时,我得到一个错误。此示例代码将重现错误:
class Shrubber:
def __init__(self, age):
self.name = 'Roger'
self.age = age
def getAge(self):
return self.age
def main():
rogerAges = [30, 21, 21, 25]
rogers = []
for rAge in rogerAges:
newShr = Shrubber(rAge)
rogers.append((newShr.getAge(), newShr))
rogers.sort()
print(rogers)
main()
我希望程序打印如下内容:
[(21, <__main__.Shrubber object at XxXEX>), (21, <__main__.Shrubber object at YxYEY>), (25, <__main__.Shrubber object at ZxZEZ>), (30, <__main__.Shrubber object at QxQEQ>)]
...但是相反,它给了我一个 TypeError:
TypeError: unorderable types: Shrubber() < Shrubber()
我确定我收到了错误,因为在 Python 遇到两个元组元素 0 的两个相同值后,它会查看元素 1 并找到一个不可排序的数据类型(一个对象)。然而,两个 Shrubbers 的年龄不能相同的限制让我好像错过了什么。
我的问题:我可以按元组元素 0 稳定地对我的元组列表进行排序并忽略我的不可排序的元组元素 1 吗?
【问题讨论】:
-
而不是键?你确定它不是在谈论比较器吗?引入关键功能的原因之一是为了优化您正在谈论的内容。
-
在 python 2.7 上为我工作
-
是的,他说不要使用键,而是为每个 2 元素元组创建具有可排序属性的字面值作为元素 0 的元组。他没有在书中介绍比较器,因为它们还没有被介绍过,并且在教科书索引中也没有条目。使用 Python 3.3。
-
那……没有意义。 key 函数只对每个列表项进行一次评估。就像你使用了 decorate-sort-undecorate 一样,但是更快更干净。我能想到使用装饰列表可能更快的唯一情况是,如果您要反复修改和重新排序列表,但即便如此,如果键函数只是获取一个属性,成本应该微不足道。
-
John Zelle(作者)说:“将函数传递给列表排序方法的一个缺点是它会使排序变慢,因为 Python 需要比较各种项目时重复调用此函数。创建特殊键函数的另一种方法是创建一个“装饰”列表,该列表将使用标准 Python 排序按所需顺序进行排序。” JZ 然后继续描述我提到的元组方案。