nos*_*nos 1 python sorting key
我有一个对象列表,想根据实例函数的返回值对它们进行排序。有两种方法可以做到这一点
from operator import methodcaller
l.sort(key=lambda x:x.f())
l.sort(key=methodcaller('f'))
Run Code Online (Sandbox Code Playgroud)
一种方式比另一种更好吗?或者这只是个人喜好?
methodcaller('f')速度更快,因为它可以在 C 代码中执行属性查找和方法调用。
lambda 增加了以下额外开销:
调用lambda必须跳出sort()C 循环回到 Python 代码中。这需要一个具有关联数据的新框架对象。
查找方法属性是一个 Python 操作码,其开销比 C 中的直接等效操作码更多。
接下来从 Python 框架调用该方法必须再次将该框架推送到 Python 调用堆栈上。C 代码也有堆栈,但这要轻得多。
从被调用的方法返回会返回到Python框架,将其从堆栈中弹出,然后返回lambda,导致函数框架再次被销毁(这仍然是更多的工作)。
您可以测量差异:
>>> from timeit import timeit
>>> timeit('m("")', 'm = lambda s: s.lower()', number=10**7)
1.2575681940070353
>>> timeit('m("")', 'from operator import methodcaller; m = methodcaller("lower")', number=10**7)
1.061251598992385
Run Code Online (Sandbox Code Playgroud)
str.lower()因此,在对空字符串进行 700 万次调用时,amethodcaller()的速度大约快 16%。
现在,如果所有数据都具有完全相同的类型,并且object.f总是绑定到相同的方法,那么您可以只使用未绑定的方法:
l.sort(key=SharedType.f)
Run Code Online (Sandbox Code Playgroud)
这样您就不必在每个实例上查找它。