推荐学习书目
› Learn Python the Hard Way
Python Sites
› PyPI - Python Package Index
› http://diveintopython.org/toc/index.html
› Pocoo
值得关注的项目
› PyPy
› Celery
› Jinja2
› Read the Docs
› gevent
› pyenv
› virtualenv
› Stackless Python
› Beautiful Soup
› 结巴中文分词
› Green Unicorn
› Sentry
› Shovel
› Pyflakes
› pytest
Python 编程
› pep8 Checker
Styles
› PEP 8
› Google Python Style Guide
› Code Style from The Hitchhiker's Guide
terence4444
V2EX  ›  Python

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

  •  2
     
  •   terence4444 · May 8, 2016 · 19226 views
    This topic created in 3837 days ago, the information mentioned may be changed or developed.
    PyCharm 推荐写成后者,这样写跑起来比较快?
    50 replies  •  2016-08-28 22:26:40 +08:00
    Shura
    Shura
    May 8, 2016 via Android
    1
    写着方便啊,而且如果要改变量名,只要改一次
    techme
    techme
    May 8, 2016
    2
    少打一个字符
    SkyEcho
    SkyEcho
    May 8, 2016 via Android
    3
    @Shura 用 ide 的重构变量名应该是最准确的,直接替换有时候会出错
    SkyEcho
    SkyEcho
    May 8, 2016 via Android
    4
    可能是编译器会有特殊处理吧
    hxtheone
    hxtheone
    May 8, 2016
    5
    会不会是前者计算出右值后会存入一个临时变量然后赋给左侧的 i, 而后者是在 i 本身上做计算, 所以效率会有一点点提升?

    个人猜测, 不对请轻喷
    chunqiuyiyu
    chunqiuyiyu
    May 8, 2016
    6
    少打一个字 提升效率 节约生命
    kalintw
    kalintw
    May 8, 2016
    7
    可以显示出 PyCharm 的存在感。哈哈。
    crab
    crab
    May 8, 2016
    8
    一样吧。和大括号另外一行
    jsonline
    jsonline
    May 8, 2016
    10
    你为什么要发帖
    junnplus
    junnplus
    May 8, 2016❤️4
    11
    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
    terence4444
    OP
    May 8, 2016
    12
    @junnplus 这是 stackoverflow 的站内搜索?搜索引擎对符号搜索视而不见……
    liuhaotian
    liuhaotian
    May 8, 2016 via iPhone
    13
    只有 i++才有效率的提高因为可以直接 INC X
    junnplus
    junnplus
    May 8, 2016
    14
    @terence4444 并不会视而不见呀,你的搜索姿势不对而已
    icybee
    icybee
    May 8, 2016
    15
    个人习惯吧, python 优化完都一样
    loveuqian
    loveuqian
    May 8, 2016
    16
    @liuhaotian
    可是 i++是异步的啊
    elarity
    elarity
    May 8, 2016
    17
    编译器喜欢,就这么简单。
    fy
    fy
    May 8, 2016❤️2
    18
    首先是看看字节码,好像区别不大

    >>> 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
    fy
    May 8, 2016
    19
    另外 Python 的 int 和 str 一样是不可变对象,根本不会有 inc x 这样的东西
    tvallday
    tvallday
    May 8, 2016
    20
    参考
    https://en.wikipedia.org/wiki/Augmented_assignment

    因为编译器并不一定知道 i 是一个普通变量,也有可能是数组里面的元素或者其他复杂类型,这样第一种写法需要找两次 i 。
    est
    est
    May 8, 2016
    21
    += 是个原子操作。 但是 py 估计然并卵。
    qqmishi
    qqmishi
    May 8, 2016 via Android❤️1
    22
    +和=是同一个键打起来快,,,
    xuboying
    xuboying
    May 8, 2016 via Android❤️1
    23
    语言搞这种细节就没意思了
    soland
    soland
    May 8, 2016
    24
    编译有可能不一样。
    RitzoneX
    RitzoneX
    May 8, 2016
    25
    试下 i++
    latyas
    latyas
    May 8, 2016
    27
    所以标题应该问:这两个写法有什么区别 会更好一些
    MntCw
    MntCw
    May 8, 2016 via Android
    28
    存储器读一次和读两次的区别
    abscon
    abscon
    May 8, 2016 via iPhone
    29
    Python 不是鼓吹只有一种方法做事情么,禁止掉一个吧
    Finalcheat
    Finalcheat
    May 8, 2016
    30
    习惯问题吧,没有任何好处。
    jacy
    jacy
    May 8, 2016
    31
    后者有 B 格
    digimoon
    digimoon
    May 8, 2016
    32
    后者我一眼看过去没反应过来是什么东西,可能似乎大概有 B 格
    mhoudg
    mhoudg
    May 8, 2016❤️2
    33
    这个步骤的真实意图通常并非做一个加法运算,而是进行自增
    i += 1 的写法非常符合 “ i 自增 1 ”这个语言顺序,给人感觉很直观;
    而 i = i + 1 的写法会让人第一感受是一个赋值,第二感受是一个假发,相对 += 来说不那么直观

    我知道肯定有人会说第二种写法也很直观,而且我不打算讨论什么叫“直观”这个问题
    Patiencec
    Patiencec
    May 8, 2016 via iPhone
    34
    哈哈,打字习惯
    chrishine
    chrishine
    May 8, 2016
    35
    语法糖层面,如果 i 这个变量名很长,优势就出来了。比如你要给某个结构体的某个字段增加某个值。
    性能方面,我觉得编译器应该可以优化掉这种 case.
    zhuangzhuang1988
    zhuangzhuang1988
    May 8, 2016
    36
    @chrishine 标准 python 解释器 是不会优化的
    Joway
    Joway
    May 8, 2016
    37
    以前忘了听谁说的说前者是一个操作,后者是两个,还有那个 ++i 和 i++ 前缀加比后缀加要快。。。然而我觉得这玩意在编译器阶段就已经被优化了,没什么区别。。
    Exin
    Exin
    May 8, 2016
    38
    可以给自己续一秒
    abcdabcd987
    abcdabcd987
    May 8, 2016
    39
    刚写完一个编译器,看到这个问题简直泪流满面。比如下面这个句子:
    a[i][j][k] = a[i][j][k] + 1
    和
    a[i][j][k] += 1
    两句话翻译出来指令数差了好多啊 T_T
    glennq
    glennq
    May 9, 2016
    40
    前者等价于 i = i.__add__(1),后者等价于 i.__iadd__(1),对于 int 这种不可变对象是没太大区别,但在可变对象的情况下不仅效率可能有较大差别,实际产生的效果也不一样。
    atpking
    atpking
    May 9, 2016
    41
    编译器会帮你优化这些的 现在的编译器已经不是石器时代了
    Ginson
    Ginson
    May 9, 2016
    42
    作为一个 0 基础新手,我还是觉得 i = i + 1 更直观些
    i + = 好在哪里?无所谓了,反正结果一样。
    iiduce
    iiduce
    May 9, 2016
    43
    当你找到自认为对的理由后,会有一种优越感。
    iverson68214
    iverson68214
    May 9, 2016
    44
    變量名長時,差別就出來了
    error_count = error_count + 1

    error_count += 1
    firemiles
    firemiles
    May 9, 2016
    45
    python 用多了连这种举手之劳就可以写成 i += 1 的优化也不愿意做了吗,什么都指望编译器能优化不太好吧。
    knightdf
    knightdf
    May 9, 2016
    46
    @iverson68214 确实,第一种丑
    sweelia
    sweelia
    May 9, 2016
    47
    i = i++ [再见]
    winoros
    winoros
    May 9, 2016
    48
    @Joway ++i 是传引用直接改, i++要先拿个变量存下当前的值,然后增,最后把变量返回
    Joway
    Joway
    May 9, 2016 via Android
    49
    @winoros 我知道你说的,但是实际上我觉得编译器已经能够优化这点了,毕竟那么多人循环都写 i++ (逃
    Override
    Override
    Aug 28, 2016
    50
    更加"dry"

    你写成 i = i + 1 的话,你要修改 i 这个变量,变成 n = n + 1 ,需要修改两个地方,
    而写成 i += 1 ,你只需要修改一个地方就可以变成 n += 1
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1226 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 107ms · UTC 17:27 · PVG 01:27 · LAX 09:27 · JFK 12:27
    ♥ Do have faith in what you're doing.