В чем разница между sorted(list)против 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]
Python 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.
Poke также запустил свой собственный код, вот код:
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"