Python 如何知道某个命令或方法是否为“就地算法”?

Python 如何知道某个命令或方法是否为“就地算法”?,python,algorithm,list,python-3.x,Python,Algorithm,List,Python 3.x,我正在学习python,我怎么知道一个命令或方法是否是一个函数 尝试“大”输入并用命令检查运行时是否足够好 例如,假设我有一个包含100000个元素的列表lst。 我检查了以下两个命令,并在一瞬间“完成”:lst=lst[::-1]和lst.reverse。那么这是否意味着两者都已就位?如果函数已就位,则它将修改调用它的对象。如果不是,那么它将返回结果 sorted(lst) # returns the sorted form of lst lst.sort() # sorts lst 就这些

我正在学习python,我怎么知道一个命令或方法是否是一个函数

尝试“大”输入并用命令检查运行时是否足够好

例如,假设我有一个包含100000个元素的列表lst。
我检查了以下两个命令,并在一瞬间“完成”:lst=lst[::-1]和lst.reverse。那么这是否意味着两者都已就位?

如果函数已就位,则它将修改调用它的对象。如果不是,那么它将返回结果

sorted(lst) # returns the sorted form of lst
lst.sort() # sorts lst

就这些。不要试图将它与运行时间或效率联系起来。

在Python中,就地操作通常返回None,因此在您的情况下,lst.reverse是就地操作,因为它返回None并修改列表。而lst[::-1]返回一个新的列表,您将该列表分配给lst


不经意间,我认为在运行程序时查看内存消耗是一个更好的指标。据我所知,这意味着运行该算法不需要或几乎不需要额外的空间

对于您的特定示例,我认为快速运行时间最有可能是由于使用了列表实现。我的第一个猜测是,列表是使用双链接列表实现的。当然,这反过来意味着将在适当的位置执行反向操作


但是,如果您想确定,我认为您需要首先跳转到实现所讨论的算法的代码中。

如果您使用类似iPython的东西,您可以询问解释器-

In [1]: x = [1, 2, 3]

In [2]: ? x.reverse
Type:       builtin_function_or_method
Base Class: <type 'builtin_function_or_method'>
String Form:<built-in method reverse of list object at 0x0362EB48>
Namespace:  Interactive
Docstring:  L.reverse() -- reverse *IN PLACE*
将不在适当位置,因为先创建副本,然后将其指定给x。你知道这是不可能的,因为有类似的任务

In [4]: y = x[::-1]

当然,我们必须创建一个额外的x副本。

要回答这个问题,我们必须首先知道什么是“就地算法”

wikipedia提供的是一种算法,该算法使用一个数据结构转换输入,该数据结构具有较小、恒定的额外存储空间

“覆盖输入”和“就地算法”之间的关系是什么:

1.如果一个覆盖了它的输入,它不是必须是一个就地算法吗? 不,例如,快速排序总是覆盖它的输入,但它需要额外的空间来跟踪递归函数调用

2.如果一个是就地算法,它是否必须覆盖其输入? 不,例如,在数组中查找最小数的算法,它是一种就地算法,只需要额外的O1空间,但不需要覆盖其输入

因此,它们之间没有绝对关系,输入通常会被就地算法覆盖

如何知道一个方法是否在一个就地算法中? 好吧,我想你必须看看它的实现,源代码,同一个方法可能会使用不同的算法,毕竟,方法或函数和算法不是一回事

顺便说一句,有一种简单的方法可以知道方法的输入是否被覆盖:

>>> lst = [1, 2, 3]
>>> id(lst)`
3070142764
>>> lst = lst[: : -1]
>>> id(lst)
3070142828
>>> lst.reverse()
>>> id(lst)
3070142828

在lst[::-1]之后,lst的id已经更改,因此lst[::-1]创建一个新的列表对象,在lst.reverse之后,lst的id没有更改,所以lst.reverse覆盖了它的输入。

你是在谈论它们的底层实现吗?@devnull我不明白这个问题。你打算如何区分O1额外空间和OA^-1n,其中A^-1是Ackermann函数的逆函数?A^-1n在任何您可能测试的输入中最多为4,因此在实际测试中它等于O1,但它不被考虑在适当的位置。@Bakuriu根据我听到的人们对union find数据结构的说法,大多数人会将OA^-1n空间视为有效的常量空间,并且不会因为称其为就地算法而吹毛求疵。@delnan well的人还说,当它使用Ologn空间时,快速排序是适当的。我的观点是,如果我们使用一个严格的就地定义,就不可能通过实验准确地确定这种算法的给定实现是否有效地占用了恒定的空间。在解释语言中,内存消耗不需要与算法的空间复杂度相关联。例如,python列表使用的内存比保存其内存所需的内存要多,以减少以下附件的成本。如果不考虑这一点,在分析内存使用情况时,可能会发现与算法空间分析结果不同的结果。@Bakuriu对动态数组的过度分配与解释或对象模型完全无关,它和数据结构决策一样不受语言的影响,其基本原理是在RAM计算模型中表述的。但你们是对的,测量内存消耗有很多陷阱。至于这个答案:列表不是一个双重链接的列表。谢天谢地,这是一个动态数组。反转一个确实很快,但它不是恒定的时间。@delnan我可能不知道
sused在这里解释,但我指的是提供足够高级操作的任何语言。例如,不是C,因为在C中,您显式分配了精确的内存量,因此,给定的C程序更容易理解给定的算法应该使用多少内存,例如python程序就不那么容易了。@Bakuriu内存管理更显式,但大部分内存仍然可以隐藏在库中。考虑像PyListObjs*L= PyListLeNe0这样的代码;PyList_附录,x;仅仅是我,还是就地算法的定义有点误导?有人说这是一种不使用任何辅助数据结构的算法。python中的一些方法(如lst.sort)不返回任何值,但sort方法可能使用辅助数据结构来执行排序,即合并排序,因此根据Wikipedia的定义,它不存在
In [4]: y = x[::-1]
>>> lst = [1, 2, 3]
>>> id(lst)`
3070142764
>>> lst = lst[: : -1]
>>> id(lst)
3070142828
>>> lst.reverse()
>>> id(lst)
3070142828