`sorted(list)`vs`list.sort()`有什么区别?

alv*_*vas 165 python sorting copy list in-place

list.sort()对列表进行排序并保存已排序的列表,同时sorted(list)返回列表的已排序副本,而不更改原始列表.

  • 但什么时候使用哪个?
  • 哪个更快?又快多少?
  • 可以在之后检索列表的原始位置list.sort()吗?

Mar*_*ers 275

sorted()返回一个新的排序列表,使原始列表不受影响.list.sort()对列表进行排序,改变列表索引,然后返回None(就像所有就地操作一样).

sorted()适用于任何可迭代的,而不仅仅是列表.字符串,元组,字典(你将得到键),生成器等,返回包含所有元素的列表,排序.

  • 使用list.sort()时要变异列表中,sorted()当你想要一个新的排序的对象返回.使用sorted()时要排序的东西,是一个可迭代,而不是一个名单尚未.

  • 对于列表,list.sort()速度比sorted()因为不必创建副本更快.对于任何其他可迭代的,您别无选择.

  • 不,您无法检索原始位置.一旦你打电话list.sort(),原始订单就消失了.

  • 通常,当python函数返回`None'时,这是一个迹象,表明操作已就位,这就是为什么当您要打印`list.sort()`时它返回None的原因。 (4认同)

Aar*_*all 36

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
Run Code Online (Sandbox Code Playgroud)

什么时候用哪个?

  • 使用list.sort时,你不希望保留原来的排序顺序(这样你就可以重新使用内存就地列表.)当你在列表的唯一所有者(如果该名单是由其他代码和你共享改变它,你可以引入使用该列表的bug.)
  • 使用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
"""
Run Code Online (Sandbox Code Playgroud)

这是我们在随机排列的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]
Run Code Online (Sandbox Code Playgroud)

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]
Run Code Online (Sandbox Code Playgroud)

在一些反馈之后,我决定另外一个具有不同特征的测试.在这里,我为每次迭代提供1000次长度为100,000的随机排序列表.

import timeit
setup = """
import random
random.seed(0)
lst = list(range(100000))
random.shuffle(lst)
"""
Run Code Online (Sandbox Code Playgroud)

我从Martijn提到的复制中解释了这种较大的差异,但它并没有在这里较老的更受欢迎的答案中所说的点上占主导地位,这里时间的增加只有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]
Run Code Online (Sandbox Code Playgroud)

我还在一个小得多的类型上运行上面的内容,并且发现新的sorted副本版本在1000种长度上仍然需要大约2%的运行时间.

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))
Run Code Online (Sandbox Code Playgroud)

他找到1000000长度排序,(运行100次)类似的结果,但只有大约5%的时间增加,这是输出:

10000000 100
l = next(it); l.sort()
610.5015971539542
l = next(it); sorted(l)
646.7786222379655
Run Code Online (Sandbox Code Playgroud)

结论:

通过sorted制作副本进行排序的大型列表可能会主导差异,但排序本身在操作中占主导地位,围绕这些差异组织代码将是过早优化.我会用sorted我所需要的数据的新的分类列表,我会用list.sort我需要梳理就地名单,并让这决定我的使用.

  • 发电机设置很好,但我不会得出结论你过快地破坏了一个神话.事实上,`sorted()`必须分配一个新的列表对象并复制引用; 其余的代码路径是相同的.看看你是否可以使用更大的列表运行相同的测试.将其与仅创建列表副本进行比较,看看是否可以复制找到的差异等. (4认同)

Chr*_*ian 9

主要区别在于sorted(some_list)返回一个新的list:

a = [3, 2, 1]
print sorted(a) # new list
print a         # is not modified
Run Code Online (Sandbox Code Playgroud)

并且some_list.sort(),对列表进行排序到位:

a = [3, 2, 1]
print a.sort() # in place
print a         # it's modified
Run Code Online (Sandbox Code Playgroud)

请注意,由于a.sort()不返回任何内容,print a.sort()将打印None.


可以在list.sort()之后检索列表原始位置吗?

不,因为它修改了原始列表.

  • `print a.sort()` 不会打印任何东西。 (2认同)

Str*_*ker 5

以下是一些简单的示例,可以看出操作上的差异:

请参阅此处的号码列表:

nums = [1, 9, -3, 4, 8, 5, 7, 14]
Run Code Online (Sandbox Code Playgroud)

当调用sorted此列表时,sorted将复制该列表(这意味着您的原始列表将保持不变。)

让我们来看看。

sorted(nums)
Run Code Online (Sandbox Code Playgroud)

回报

[-3, 1, 4, 5, 7, 8, 9, 14]
Run Code Online (Sandbox Code Playgroud)

nums再看一遍

nums
Run Code Online (Sandbox Code Playgroud)

我们看到原始列表(未更改且未排序)。sorted没有改变原来的名单

[1, 2, -3, 4, 8, 5, 7, 14]
Run Code Online (Sandbox Code Playgroud)

获取相同的nums列表并sort对其应用函数,将更改实际的列表。

让我们来看看。

从我们的nums列表开始,以确保内容仍然相同。

nums

[-3, 1, 4, 5, 7, 8, 9, 14]

nums.sort()
Run Code Online (Sandbox Code Playgroud)

现在原始的 nums 列表已更改,查看 nums 我们看到原始列表已更改并且现已排序。

nums
[-3, 1, 2, 4, 5, 7, 8, 14]
Run Code Online (Sandbox Code Playgroud)


Pro*_*mik 5

注意:sort()和sorted()之间最简单的区别是:sort()不返回任何值,而sorted()返回一个可迭代列表。

sort() 不返回任何值。

sort() 方法只是按特定顺序对给定列表的元素进行排序 - 升序或降序,而不返回任何值。

sort()方法的语法是:

list.sort(key=..., reverse=...)
Run Code Online (Sandbox Code Playgroud)

或者,您也可以使用Python的内置函数sorted()来达到相同的目的。排序函数返回排序列表

 list=sorted(list, key=..., reverse=...)
Run Code Online (Sandbox Code Playgroud)