我知道整数是不可变的,因此计算出的值不会修改原始整数。因此,就地操作应该与简单操作相同,即先计算值,再将值重新分配回变量。但是为什么就地操作比简单操作慢?
import timeit
print("a = a + 1: ", end="")
print(timeit.timeit("for i in range(100): a = a + 1", setup="a = 0"))
print("a += 1: ", end="")
print(timeit.timeit("for i in range(100): a += 1", setup="a = 0"))
print("a = a - 1: ", end="")
print(timeit.timeit("for i in range(100): a = a - 1", setup="a = 0"))
print("a -= 1: ", end="")
print(timeit.timeit("for i in range(100): a -= 1", setup="a = 0"))
print("a = a * 1: ", end="")
print(timeit.timeit("for i in range(100): a = a * 1", setup="a = 1"))
print("a *= 1: ", end="")
print(timeit.timeit("for i in range(100): a *= 1", setup="a = 1"))
print("a = a // 1: ", end="")
print(timeit.timeit("for i in range(100): a = a // 1", setup="a = 1"))
print("a //= 1: ", end="")
print(timeit.timeit("for i in range(100): a //= 1", setup="a = 1"))
输出:
a = a + 1: 2.922127154
a += 1: 2.9701245480000003
a = a - 1: 2.9568866799999993
a -= 1: 3.1065419050000003
a = a * 1: 2.2483990140000003
a *= 1: 2.703524648
a = a // 1: 2.534561783000001
a //= 1: 2.6582312889999997
所有原地操作都比简单操作要慢。加法的差距最小,而乘法的差距最大。
//=
比a = a // b
更快,而+=
比a = a + b
更快。 - S.Bint
对象实际上没有实现原地操作符,因此在检查int.__iadd__
时会有一些开销,发现不存在,然后会执行__add__
...尽管如此,这并不能解释相对差异... - juanpa.arrivillaga+=
不是一个“原地”运算符 - 原地算法 意味着它应该在不分配与输入大小成比例的新内存的情况下改变输入;但是对于整数的+=
并不会改变原始整数,而是创建一个需要为其分配内存的新对象。Python 语言参考将+=
定义为增强赋值运算符,并且仅表示实现此类运算符的类应在可能的情况下进行原地操作。 - kaya3