I was experimenting with python sorting using key. I'm interested in the inner working of the algorithm. Is it roughly equivalent to Schwartzian transform (Decorate-Sort-Undecorate)触发不同的过滤器?
特别是:
(key, orginal_value)
还是使用其他方法。我使用了以下测试程序
class Isbn:
def __init__(self, isbn_num):
self.isbn_num = isbn_num
def __lt__(self, other):
print(f"__lt__ {self.isbn_num} {other.isbn_num}")
return self.isbn_num < other.isbn_num
def __repr__(self) -> str:
return f'Isbn({self.isbn_num})'
class Book:
def __init__(self, isbn):
self.isbn = Isbn(isbn)
def __repr__(self) -> str:
return f'Book({self.isbn})'
@property
def key(self):
print(f"key {self.isbn}")
return self.isbn
books = [Book(5), Book(10), Book(6), Book(2)]
books.sort(key=lambda b: b.key)
print(books)
哪个给出以下输出:
key Isbn(5)
key Isbn(10)
key Isbn(6)
key Isbn(2)
__lt__ 10 5
__lt__ 6 10
__lt__ 6 10
__lt__ 6 5
__lt__ 2 6
__lt__ 2 5
[Book(Isbn(2)), Book(Isbn(5)), Book(Isbn(6)), Book(Isbn(10))]
答案 0 :(得分:1)
是的,在某些情况下,Python确实使用了Schwartzian transform
。
来自this documentation。
Python程序员在比较操作可能比较昂贵的情况下使用转换。
答案 1 :(得分:1)
专门讨论CPython(可使用其他Python实现):
它确实进行转换。当前,它在开始排序之前会构建一个C键数组。这完全是用C语言完成的-因此它不是Python列表。不涉及Python元组。
这是摘自listobject.c
的(当前)相关C代码的摘录(当然,这会随着CPython的发展而改变)。
key_func
是关键功能。 saved_ob_size
是列表的长度。 saved_ob_item
是原始列表中的数组。
2239 if (keyfunc == NULL) {
...
2243 }
2244 else {
...
2256 for (i = 0; i < saved_ob_size ; i++) {
2257 keys[i] = PyObject_CallFunctionObjArgs(keyfunc, saved_ob_item[i],
2258 NULL);
...
2265 }
2266 }