【问题标题】:Design reason behind having some functions modify the object in-place让某些功能就地修改对象的设计原因
【发布时间】:2022-07-08 05:06:17
【问题描述】:
让random.shuffle就地修改列表而不是返回新列表的设计原因是什么?
假设,例如,str.replace() 返回一个新字符串,并且考虑到字符串是不可变的,不可能有任何其他方式,如果random.shuffle() 返回一个新列表不是更一致吗?
【问题讨论】:
-
我不认为不可变对象上的方法(正如您所说的那样不可能是其他任何方式)对于需要可变序列的函数来说是一件好事。还有很多其他 Python 方法和函数可以就地操作,要遵守的约定是它们都返回 None。正如the docs 所说,如果您想要一个新的混洗列表(或想要混洗一个像元组这样的不可变序列),您可以使用sample(x, k=len(x)) 作为替代方案。
标签:
python
language-design
【解决方案1】:
当您有一个(大)可变容器时,就地修改它可能比创建一个新容器更有效。但对于 tuple 或 str 这样的不可变类型,不能选择。
【解决方案2】:
大多数列表或数组混洗实现使用 Durstenfeld 的 Fisher-Yates 算法变体(在 Knuth 的计算机编程艺术,第 2 卷,第 3.4.2 节中也称为“算法 P”)。该算法的优点是它在 O(n) 时间内完成,并且需要 O(1) 额外的内存(在 O(n) em> 现有列表需要开始的空间)。这比在每个步骤中创建一个新列表要高效得多。即使在纯函数环境中,库实现也可能会制作原始列表的初始副本,然后应用此(变异)算法。这不会是纯粹的功能,而是完全隐藏在调用代码中。此外,通过制作一次性副本,可以轻松地将实现从就地修改转换为更纯粹的功能样式。然而,正如其他人所指出的,根据针对特定库观察到的其他原则,设计人员可能会选择不这样做。