Яка різниця між sorted(list)vs list.sort()?
list.sort вимкнення списку на місці та повернення None
sorted бере будь-який ітерабельний і повертає новий список, відсортований.
sorted еквівалентно цій реалізації Python, але вбудована CPython функція повинна працювати помірно швидше, як це написано на C:
def sorted(iterable, key=None):
new_list = list(iterable) # make a new list
new_list.sort(key=key) # sort it
return new_list # return it
коли використовувати який?
- Використовуйте,
list.sortколи ви не бажаєте зберігати оригінальний порядок сортування (таким чином, ви зможете повторно використовувати список на місці в пам’яті.) І коли ви є єдиним власником списку (якщо цей список наданий іншим кодом, і ви вимкніть його, ви можете ввести помилки, де використовується цей список.)
- Використовуйте,
sortedколи ви хочете зберегти початковий порядок сортування або коли ви хочете створити новий список, яким володіє лише ваш місцевий код.
Чи можна отримати вихідні позиції списку після list.sort ()?
Ні - якщо ви самі не зробили копію, ця інформація втрачається, оскільки сортування робиться на місці.
"А що швидше? І наскільки швидше?"
Для ілюстрації покарання створення нового списку використовуйте модуль timeit, ось наша настройка:
import timeit
setup = """
import random
lists = [list(range(10000)) for _ in range(1000)] # list of lists
for l in lists:
random.shuffle(l) # shuffle each list
shuffled_iter = iter(lists) # wrap as iterator so next() yields one at a time
"""
І ось наші результати щодо списку випадково розташованих 10000 цілих чисел, як ми бачимо тут, ми спростували міф про створення старих списків :
Python 2.7
>>> timeit.repeat("next(shuffled_iter).sort()", setup=setup, number = 1000)
[3.75168503401801, 3.7473005310166627, 3.753129180986434]
>>> timeit.repeat("sorted(next(shuffled_iter))", setup=setup, number = 1000)
[3.702025591977872, 3.709248117986135, 3.71071034099441]
Пітон 3
>>> timeit.repeat("next(shuffled_iter).sort()", setup=setup, number = 1000)
[2.797430992126465, 2.796825885772705, 2.7744789123535156]
>>> timeit.repeat("sorted(next(shuffled_iter))", setup=setup, number = 1000)
[2.675589084625244, 2.8019039630889893, 2.849375009536743]
Після деяких відгуків, я вирішив, що ще один тест буде бажаним з різними характеристиками. Тут я надаю той самий випадково упорядкований список довжиною 100 000 за кожну ітерацію 1000 разів.
import timeit
setup = """
import random
random.seed(0)
lst = list(range(100000))
random.shuffle(lst)
"""
Я інтерпретую цю різницю різного роду від копіювання, згаданого Мартійна, але це не домінує до моменту, зазначеного в більш старій більш популярній відповіді тут, тут збільшення часу становить лише приблизно 10%
>>> timeit.repeat("lst[:].sort()", setup=setup, number = 10000)
[572.919036605, 573.1384446719999, 568.5923951]
>>> timeit.repeat("sorted(lst[:])", setup=setup, number = 10000)
[647.0584738299999, 653.4040515829997, 657.9457361929999]
Я також запустив вищезазначене на набагато менший сорт і побачив, що нова sortedверсія копії все ще займає приблизно 2% більше часу роботи на 1000 довжини.
Пок також запустив власний код, ось код:
setup = '''
import random
random.seed(12122353453462456)
lst = list(range({length}))
random.shuffle(lst)
lists = [lst[:] for _ in range({repeats})]
it = iter(lists)
'''
t1 = 'l = next(it); l.sort()'
t2 = 'l = next(it); sorted(l)'
length = 10 ** 7
repeats = 10 ** 2
print(length, repeats)
for t in t1, t2:
print(t)
print(timeit(t, setup=setup.format(length=length, repeats=repeats), number=repeats))
Він знайшов для 1000000 сорти довжини (пробіг 100 разів) аналогічний результат, але лише приблизно на 5% збільшення часу, ось результат:
10000000 100
l = next(it); l.sort()
610.5015971539542
l = next(it); sorted(l)
646.7786222379655
Висновок:
Список великих розмірів, відсортований із sortedстворенням копії, ймовірно, буде домінувати у відмінностях, але саме сортування домінує над операцією, а організація коду навколо цих відмінностей буде передчасною оптимізацією. Я б використовував, sortedколи мені потрібен новий відсортований список даних, і я б використовував, list.sortколи мені потрібно сортувати список на місці, і нехай це визначає моє використання.
sorted()на аргумент рядка, але думаєте, що це список, ви отримаєте результат списку, а не рядок : неsorted("abcd", reverse=True)дає['d', 'c', 'b', 'a']"dcba"