为啥 '.sort()' 导致列表在 Python 中为 'None'? [复制]

Posted

技术标签:

【中文标题】为啥 \'.sort()\' 导致列表在 Python 中为 \'None\'? [复制]【英文标题】:Why does '.sort()' cause the list to be 'None' in Python? [duplicate]为什么 '.sort()' 导致列表在 Python 中为 'None'? [复制] 【发布时间】:2012-04-04 08:22:10 【问题描述】:

我正在尝试对 ints 的 Python 列表进行排序,然后使用 .pop() 函数返回最高的列表。我尝试过以不同的方式编写方法:

def LongestPath(T):    
    paths = [Ancestors(T,x) for x in OrdLeaves(T)]
    #^ Creating a lists of lists of ints, this part works
    result =[len(y) for y in paths ]
    #^ Creating a list of ints where each int is a length of the a list in paths
    result = result.sort()
    #^meant to sort the result
    return result.pop()
    #^meant to return the largest int in the list (the last one)

我也试过了

def LongestPath(T):
    return[len(y) for y in [Ancestors(T,x) for x in OrdLeaves(T)] ].sort().pop()

在这两种情况下.sort() 导致列表为None(它没有.pop() 函数并返回错误)。当我删除 .sort() 时,它可以正常工作,但不会返回最大的 int,因为列表未排序。

【问题讨论】:

有什么理由不使用max() hc_,当我这样做时,我会收到 AttributeError: 'list' object has no attribute 'max' 那是因为max() 是一个函数,而不是list 方法。 来自 Python documentation:“您可能已经注意到,仅修改列表的插入、删除或排序等方法没有打印返回值——它们返回默认值 None。这是Python 中的所有可变数据结构。” 【参考方案1】:

简单地删除分配

result = result.sort()

离开

result.sort()

sort 方法就地工作(它修改现有列表),因此不需要赋值,它返回None。当您将其结果分配给列表名称时,您分配的是None

它可以很容易(并且更有效地)写成单行:

max(len(Ancestors(T,x)) for x in OrdLeaves(T))

max 以线性时间 O(n) 运行,而排序时间为 O(nlogn)。您也不需要嵌套列表推导,一个生成器表达式就可以了。

【讨论】:

好的,那么为什么第二种方法不起作用呢?为什么用 .sort() 返回列表会导致它返回 None @Btuman 因为当您尝试.pop() 时,您仍在访问.sort() 的返回值——所以您尝试在两者中都执行None.pop(),而不是sortedlist.pop()版本。如果您真的想要使用单行和排序而不是max,您应该使用sorted(len(Ancestors(T,x)) for x in OrdLeaves(T))[-1].pop() 做了两件事——它删除并返回最后一个值。既然只需要退回,不用删除,就用[-1]吧。 @Btuman 需要明确的是,.sort() 不会“导致列表为None”,它只是返回None。但是,当您将 None 分配给名称 result 时,您将无法访问排序列表——result 不再指向它。同一行中也发生了同样的事情——当您执行.sort() 时,您将无法访问列表,因为您只能访问内部表达式的结果,而.sort() 的结果是None不是它修改的列表。【参考方案2】:

这个

result = result.sort()

应该是这样的

result.sort()

在 Python 中,改变序列的方法返回 None 是一种约定。

考虑:

>>> a_list = [3, 2, 1]
>>> print a_list.sort()
None
>>> a_list
[1, 2, 3]

>>> a_dict = 
>>> print a_dict.__setitem__('a', 1)
None
>>> a_dict
'a': 1

>>> a_set = set()
>>> print a_set.add(1)
None
>>> a_set
set([1])

此设计决策背后的 Python 设计和历史常见问题解答 gives the reasoning(关于列表):

为什么list.sort() 不返回排序后的列表?

在性能很重要的情况下,制作列表的副本 只是为了排序会很浪费。因此,list.sort() 对 清单到位。为了提醒你这个事实,它不会返回 排序的列表。这样你就不会不小心上当了 当您需要排序副本但还需要保留时覆盖列表 周围未排序的版本。

在 Python 2.4 中添加了一个新的内置函数 - sorted()。 此函数从提供的迭代创建一个新列表,对其进行排序 并返回它。

【讨论】:

【参考方案3】:

.sort() 返回 None 并对列表进行就地排序。

【讨论】:

【参考方案4】:

这已被正确回答:list.sort() 返回None。原因是“命令-查询分离”:

http://en.wikipedia.org/wiki/Command-query_separation

Python 返回None,因为每个函数都必须返回一些东西,并且约定是不产生任何有用值的函数应该返回None

我以前从未见过您在它引用的行之后放置注释的约定,而是以克拉开头的注释指向该行。请将 cmets 放在它们引用的行之前。

虽然您可以使用.pop() 方法,但您也可以只为列表编制索引。列表中的最后一个值始终可以使用-1 进行索引,因为在 Python 中,负索引“环绕”并从末尾向后索引。

但我们可以进一步简化。您对列表进行排序的唯一原因是您可以找到它的最大值。为此,Python 中有一个内置函数:max()

使用list.sort() 需要构建一个完整的列表。然后,您将从列表中提取一个值并将其丢弃。 max() 将消耗一个迭代器,而无需分配大量内存来存储列表。

此外,在 Python 中,社区更喜欢使用称为 PEP 8 的编码标准。在 PEP 8 中,您应该使用小写来表示函数名称,并使用下划线来分隔单词,而不是 CamelCase。

http://www.python.org/dev/peps/pep-0008/

考虑到上述 cmets,这是我对您的函数的重写:

def longest_path(T):
    paths = [Ancestors(T,x) for x in OrdLeaves(T)]
    return max(len(path) for path in paths)

在对max() 的调用中,我们有一个“生成器表达式”,它计算列表paths 中每个值的长度。 max() 会从中提取值,保持最大,直到所有值都用完。

但现在很明显,我们甚至不需要paths 列表。这是最终版本:

def longest_path(T):
    return max(len(Ancestors(T, x)) for x in OrdLeaves(T))

我实际上认为带有显式 paths 变量的版本更具可读性,但这并不可怕,如果可能有大量路径,您可能会注意到由于不构建和销毁paths 列表。

【讨论】:

【参考方案5】:

list.sort() 不返回列表 - 它会破坏性地修改您正在排序的列表:

In [177]: range(10)
Out[177]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [178]: range(10).sort()

In [179]:

也就是说,max 会在列表中找到最大的元素,并且会比您的方法更有效。

【讨论】:

【参考方案6】:

在 Python 中,sort() 是一个就地操作。所以result.sort() 返回None,但更改result 以进行排序。所以为了避免你的问题,当你调用sort()时不要覆盖result

【讨论】:

【参考方案7】:

有什么理由不使用sorted 函数吗? sort() 仅在列表上定义,但 sorted() 可与任何可迭代对象一起使用,并按您期望的方式运行。排序详情见this article。

另外,因为它内部使用timsort,所以如果你需要先按key 1排序,然后按key 2排序,效率会很高。

【讨论】:

【参考方案8】:

你想要实现的东西不需要自定义函数,你首先需要了解你正在使用的方法!

sort()在python中创建一个列表就位,也就是说,从sort()返回的是None。列表本身已修改返回一个新列表。

>>>results = ['list','of','items']
>>>results

['list','of','items']

>>>results.sort()
>>>type(results)

<type 'list'>

>>>results

['items','list','of']

>>>results = results.sort()
>>>results
>>>
>>>type(results)

<type 'NoneType'>

如您所见,当您尝试分配 sort() 时,您不再拥有列表类型。

【讨论】:

以上是关于为啥 '.sort()' 导致列表在 Python 中为 'None'? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

python 为啥我修改列表一个元素会导致所有元素都被修改

集合列表上的Python .sort()返回无[重复]

简单的 Python 问题:为啥我不能将变量分配给排序列表(就地)? [复制]

为啥我在使用 PySimpleGUI 的 while 循环中对列表框的更新最终导致我的程序挂起?

Python对列表排序函数sort()和reverse()的讲解

为啥 sorted(by:) 有效但 sort(by:) 在 ForEach 循环中无效