如何找出python中的特定方法是"in-place"还是不是?

How to find out a specific method in python is "in-place" or not?

我找不到区分就地方法和python中的可分配方法的方便方法。 我的意思是,例如像 my_list.sort() 这样的方法不需要赋值,它会自行改变(它是 就地 对吗?),但其他一些方法需要赋值给多变的。 我错了吗?

您无法轻易找到这种区别的原因是,除非按照脆弱的约定,否则它实际上并不存在。 “就地”仅意味着函数修改可变参数的数据,而不是 returning 一个全新的对象。如果“非就地”被认为是一个函数 return 是一个封装更新数据的新对象,单独留下输入,那么有太多其他可能的约定值得编目。

没有return一个值的standard library does its best to follow the convention of not returning values from single-argument in-place functions. So for example you have list.sort, list.append, random.shuffle and heapq.heapify all operate in-place, returning None. At the same time, you have functions and methods that create new objects, and must therefore return them, like sorted, list.__add__ and tuple.__iadd__. But you also have in-place methods that must return a value like list.__iadd__ (compare to list.extend

__iadd__ 和类似的就地运算符强调了一个非常重要的点,即就地运算不是不可变对象的选项。 Python 有一个解决方法:

x = (1, 2)
y = (3, 4)
x += y

对于所有对象,第三行相当于

x = type(x).__iadd__(x, y)

忽略该方法作为函数调用的事实,请注意名称 x 已重新分配,因此即使 x += y 必须创建一个新对象(例如,因为 tuple是不可变的),你仍然可以通过名称x看到它。在这种情况下,可变对象通常只是 return x,因此方法调用将 出现 而不是 return 一个值,即使它确实如此.

有趣的是,重新分配有时会导致意外错误:

>>> z = ([],)
>>> z[0].extend([1, 2])  # OK
>>> z[0] += [3, 4]  # Error! But list is mutable!

很多第三方库,例如numpy, support the convention of in-place functions without a return value, up to a point. Most numpy functions create new objects, like np.cumsum, np.add, and np.sort. However, there are in also functions and methods that operate in-place and return None, like np.ndarray.sort and np.random.shuffle

numpy 可以使用大内存缓冲区,这意味着通常需要就地操作。 一些函数和方法(最值得注意的是通用函数)没有一个单独的就地版本的函数,而是有一个可以设置为输入的out参数,比如np.cumsum, np.ndarray.cumsum, and np.add。在这些情况下,该函数将就地运行,但仍然 return 对 out 参数的引用,与 python 的就地运算符的方式非常相似。

更复杂的是,并非所有函数和方法都对单个对象执行单个操作。你可以这样写一个class来说明:

class Test:
    def __init__(self, value):
        self.value = value
    def op(self, other):
         other.value += self.value
         return self

此 class 修改了另一个对象,但 return 引用了未修改的 self。虽然人为设计,但该示例用于说明 in-place/not-in-place 范式并非无所不包。

TL;DR

最后,in-place 的一般概念通常很有用,但不能取代阅读文档和了解每个函数在单独基础上的作用的需要。这也将使您免于许多常见的陷阱,可变对象支持就地操作,而不可变对象只是模拟它们。