为啥 '.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 【问题描述】:我正在尝试对 int
s 的 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 问题:为啥我不能将变量分配给排序列表(就地)? [复制]
为啥我在使用 PySimpleGUI 的 while 循环中对列表框的更新最终导致我的程序挂起?