i = i +1 写成 i += 1 有什么好处?

2016-05-08 14:29:07 +08:00
 terence4444
PyCharm 推荐写成后者,这样写跑起来比较快?
17559 次点击
所在节点    Python
50 条回复
Shura
2016-05-08 14:33:45 +08:00
写着方便啊,而且如果要改变量名,只要改一次
techme
2016-05-08 14:40:08 +08:00
少打一个字符
a302800411
2016-05-08 14:45:02 +08:00
@Shura 用 ide 的重构变量名应该是最准确的,直接替换有时候会出错
a302800411
2016-05-08 14:45:39 +08:00
可能是编译器会有特殊处理吧
hxtheone
2016-05-08 14:46:17 +08:00
会不会是前者计算出右值后会存入一个临时变量然后赋给左侧的 i, 而后者是在 i 本身上做计算, 所以效率会有一点点提升?

个人猜测, 不对请轻喷
chunqiuyiyu
2016-05-08 14:46:33 +08:00
少打一个字 提升效率 节约生命
kalintw
2016-05-08 14:47:28 +08:00
可以显示出 PyCharm 的存在感。哈哈。
crab
2016-05-08 14:51:43 +08:00
一样吧。和大括号另外一行
junnplus
2016-05-08 14:53:42 +08:00
jsonline
2016-05-08 14:55:00 +08:00
你为什么要发帖
junnplus
2016-05-08 14:59:36 +08:00
In [4]: dis.dis('i = 0; i += 1')
....0 LOAD_CONST.... 0 (0)
....3 STORE_NAME....0 (i)
....6 LOAD_NAME....0 (i)
....9 LOAD_CONST....1 (1)
....12 INPLACE_ADD
....13 STORE_NAME....0 (i)
....16 LOAD_CONST....2 (None)
....19 RETURN_VALUE

In [5]: dis.dis('i = 0; i = i + 1')
....0 LOAD_CONST....0 (0)
....3 STORE_NAME....0 (i)
....6 LOAD_NAME....0 (i)
....9 LOAD_CONST....1 (1)
....12 BINARY_ADD
....13 STORE_NAME....0 (i)
....16 LOAD_CONST....2 (None)
....19 RETURN_VALUE


可以看出来,两者的区别只在 INPLACE_ADD 和 BINARY_ADD 上面
terence4444
2016-05-08 15:07:10 +08:00
@junnplus 这是 stackoverflow 的站内搜索?搜索引擎对符号搜索视而不见……
liuhaotian
2016-05-08 15:09:34 +08:00
只有 i++才有效率的提高因为可以直接 INC X
junnplus
2016-05-08 15:16:18 +08:00
@terence4444 并不会视而不见呀,你的搜索姿势不对而已
icybee
2016-05-08 15:18:02 +08:00
个人习惯吧, python 优化完都一样
loveuqian
2016-05-08 15:19:33 +08:00
@liuhaotian
可是 i++是异步的啊
elarity
2016-05-08 15:20:57 +08:00
编译器喜欢,就这么简单。
fy
2016-05-08 15:27:18 +08:00
首先是看看字节码,好像区别不大

>>> import dis
>>> dis.dis('a += 1')
1 0 LOAD_NAME 0 (a)
3 LOAD_CONST 0 (1)
6 INPLACE_ADD
7 STORE_NAME 0 (a)
10 LOAD_CONST 1 (None)
13 RETURN_VALUE
>>>
>>> dis.dis('a = a + 1')
1 0 LOAD_NAME 0 (a)
3 LOAD_CONST 0 (1)
6 BINARY_ADD
7 STORE_NAME 0 (a)
10 LOAD_CONST 1 (None)
13 RETURN_VALUE
>>>

然后去看字节码解析,貌似一毛一样

ceval.c

TARGET(BINARY_ADD) {
PyObject *right = POP();
PyObject *left = TOP();
PyObject *sum;
if (PyUnicode_CheckExact(left) &&
PyUnicode_CheckExact(right)) {
sum = unicode_concatenate(left, right, f, next_instr);
/* unicode_concatenate consumed the ref to v */
}
else {
sum = PyNumber_Add(left, right);
Py_DECREF(left);
}
Py_DECREF(right);
SET_TOP(sum);
if (sum == NULL)
goto error;
DISPATCH();
}

TARGET(INPLACE_ADD) {
PyObject *right = POP();
PyObject *left = TOP();
PyObject *sum;
if (PyUnicode_CheckExact(left) && PyUnicode_CheckExact(right)) {
sum = unicode_concatenate(left, right, f, next_instr);
/* unicode_concatenate consumed the ref to v */
}
else {
sum = PyNumber_InPlaceAdd(left, right);
Py_DECREF(left);
}
Py_DECREF(right);
SET_TOP(sum);
if (sum == NULL)
goto error;
DISPATCH();
}

然后观察实现:

abstract.c

PyObject *
PyNumber_Add(PyObject *v, PyObject *w)
{
PyObject *result = binary_op1(v, w, NB_SLOT(nb_add));
if (result == Py_NotImplemented) {
PySequenceMethods *m = v->ob_type->tp_as_sequence;
Py_DECREF(result);
if (m && m->sq_concat) {
return (*m->sq_concat)(v, w);
}
result = binop_type_error(v, w, "+");
}
return result;
}


PyObject *
PyNumber_InPlaceAdd(PyObject *v, PyObject *w)
{
PyObject *result = binary_iop1(v, w, NB_SLOT(nb_inplace_add),
NB_SLOT(nb_add));
if (result == Py_NotImplemented) {
PySequenceMethods *m = v->ob_type->tp_as_sequence;
Py_DECREF(result);
if (m != NULL) {
binaryfunc f = NULL;
f = m->sq_inplace_concat;
if (f == NULL)
f = m->sq_concat;
if (f != NULL)
return (*f)(v, w);
}
result = binop_type_error(v, w, "+=");
}
return result;
}

于是我思考之后得出了结论:
他们有什么不同呢?最终调用的槽不同。

但是 python 代码来测试的结果,确实是 += 比 = + 快一点
fy
2016-05-08 15:28:30 +08:00
另外 Python 的 int 和 str 一样是不可变对象,根本不会有 inc x 这样的东西
tvallday
2016-05-08 15:28:31 +08:00
参考
https://en.wikipedia.org/wiki/Augmented_assignment

因为编译器并不一定知道 i 是一个普通变量,也有可能是数组里面的元素或者其他复杂类型,这样第一种写法需要找两次 i 。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/277115

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX