您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

“ lambda”与“ operator.attrgetter('xxx')”作为排序键功能

“ lambda”与“ operator.attrgetter('xxx')”作为排序键功能

当仅在attrgetter('attributename')和之间lambda o: o.attributename作为排序键进行选择时,则使用attrgetter()是两者中 较快的 选项。

请记住,在排序之前,键函数仅对列表中的每个元素应用一次,因此,为了进行比较,我们可以在时间试用中直接使用它们:

>>> from timeit import Timer
>>> from random import randint
>>> from dataclasses import dataclass, field
>>> @dataclass
... class Foo:
...     bar: int = field(default_factory=lambda: randint(1, 10**6))
...
>>> testdata = [Foo() for _ in range(1000)]
>>> def test_function(objects, key):
...     [key(o) for o in objects]
...
>>> stmt = 't(testdata, key)'
>>> setup = 'from __main__ import test_function as t, testdata; '
>>> tests = {
...     'lambda': setup + 'key=lambda o: o.bar',
...     'attrgetter': setup + 'from operator import attrgetter; key=attrgetter("bar")'
... }
>>> for name, tsetup in tests.items():
...     count, total = Timer(stmt, tsetup).autorange()
...     print(f"{name:>10}: {total / count * 10 ** 6:7.3f} microseconds ({count} repetitions)")
...
    lambda: 130.495 microseconds (2000 repetitions)
attrgetter:  92.850 microseconds (5000 repetitions)

因此,应用attrgetter('bar')1000次大约比a快40μs lambda。这是因为调用 Python 函数具有一定的开销,而不是调用诸如产生的原生函数attrgetter()

这种速度优势也转化为更快的排序:

>>> def test_function(objects, key):
...     sorted(objects, key=key)
...
>>> for name, tsetup in tests.items():
...     count, total = Timer(stmt, tsetup).autorange()
...     print(f"{name:>10}: {total / count * 10 ** 6:7.3f} microseconds ({count} repetitions)")
...
    lambda: 218.715 microseconds (1000 repetitions)
attrgetter: 169.064 microseconds (2000 repetitions)
其他 2022/1/1 18:31:10 有613人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶