为毛 python 没有自增自减运算? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
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
kevinroot
V2EX    Python

为毛 python 没有自增自减运算?

  •  
  •   kevinroot
    adin283 2014-02-19 12:35:35 +08:00 16603 次点击
    这是一个创建于 4259 天前的主题,其中的信息可能已经有所发展或是发生改变。
    每次写到count += 1就ju花一紧
    42 条回复    2016-03-07 19:15:31 +08:00
    dorentus
        1
    dorentus  
       2014-02-19 12:42:52 +08:00
    因为不好看……
    hitsmaxft
        2
    hitsmaxft  
       2014-02-19 12:44:23 +08:00 via iPhone
    因为作者很懒
    loading
        3
    loading  
       2014-02-19 12:46:35 +08:00 via iPhone
    难道你还怀念考C语言
    i++
    ++i
    的头晕日子?

    程序是给人看的!
    tonitech
        4
    tonitech  
       2014-02-19 12:50:08 +08:00   1
    举个例子
    foo=1
    bar=1
    foo现在和bar的地址实际上是相同的,
    当foo+1变成2之后,它的那个啥,地址就跟之前不一样了。。。
    应该说是概念不同吧。。。
    chevalier
        5
    chevalier  
       2014-02-19 12:59:18 +08:00
    i++ 这种操作在C刚诞生的那会,很有用,因为相对于i=i+1可以节约两个字节的空间,那时候的内存真的在乎这两个字节。后来其他语言如Java只不过考虑到程序员的习惯沿用了这一用法。
    在今天,已经不用考虑这两个字节了,为了程序的可读性,还是写成i=i+1比较好,Python中就去掉i++这种用法了。
    VYSE
        6
    VYSE  
       2014-02-19 13:08:17 +08:00   3
    http://stackoverflow.com/questions/3654830/why-are-there-no-and-operators-in-python

    我觉得第二个回答很好,++ -- 更多是为了让当年不聪明的编译器翻译成 inc operand / dec operand 而不是俩mov然后add
    今天则不需要,结果养成了一种病
    est
        7
    est  
       2014-02-19 13:25:44 +08:00
    @VYSE python的 += 1 依然不是原子操作。。。。。
    VYSE
        8
    VYSE  
       2014-02-19 13:34:18 +08:00
    @est 有GIL保障就好,毕竟不是native的
    chilaoqi
        9
    chilaoqi  
       2014-02-19 13:55:25 +08:00
    python 追求 readability
    ivenvd
        10
    ivenvd  
       2014-02-19 14:08:36 +08:00
    因为 Python 基本上用不到自加自减,不是么?
    tonitech
        11
    tonitech  
       2014-02-19 14:09:44 +08:00
    @VYSE 但是我觉得++很优美啊。。。
    tonitech
        12
    tonitech  
       2014-02-19 14:10:38 +08:00
    @chilaoqi ++去掉就提升了readability吗?
    yegle
        13
    yegle  
       2014-02-19 14:11:15 +08:00
    @est 我靠!不是原子操作是个什么情况!!!
    Ever
        14
    Ever  
       2014-02-19 14:12:51 +08:00
    python的数值是immutable的.
    zzNucker
        15
    zzNucker  
       2014-02-19 14:13:25 +08:00   1
    看到楼主写的ju花一紧,下意识看了下tag
    yegle
        16
    yegle  
       2014-02-19 14:24:17 +08:00   1
    补充14楼 @Ever的说明

    In [35]: i = 1

    In [36]: id(i)
    Out[36]: 4474635968

    In [37]: i = 2

    In [38]: id(i)
    Out[38]: 4474636000

    In [39]: i = 1

    In [40]: id(i)
    Out[40]: 4474635968
    oio
        17
    oio  
       2014-02-19 14:25:05 +08:00
    看了一下,i += 1 用的是 INPLACE_ADD, i = i+1 用的是 BINARY_ADD, 这两者效率有区别?具体实现是不是得看Cpython源码....
    est
        18
    est  
       2014-02-19 14:32:01 +08:00
    @yegle

    如果没记错的话

    http://effbot.org/zone/thread-synchronization.htm

    > The reason for this is that the increment operation is actually executed in three steps;

    python解释器有很多脑残举动。。。比如代码里 1+1 可以自动优化成一个常量但是1 + 2 * 3就不行。


    >>> from dis import dis
    >>> def f(): return 1 + 2 * 3
    >>> dis(f)




    大家可以自己去python看看结果。v2ex贴代码比较乱就不贴了。反正笑死人了。
    oldcai
        19
    oldcai  
    PRO
       2014-02-19 14:33:44 +08:00
    python很多东西都没有:还比如switch,条件语句里面的赋值。
    当然,以及楼主所说的++和--,这些在刚转入python的时候是让人很不习惯,我也吐槽过,但是习惯了也就好了,有其他办法实现目的。

    @chevalier 编译后都是一样的,省不到,只是让编码减少一点而已。
    est
        20
    est  
       2014-02-19 14:42:20 +08:00
    @oldcai 这个倒是有啊

    func_map = {value1: func1, value2: func2}

    func_map.get(my_value, default_func)(*args, **kwargs)

    巨型分支效率比switch高

    哈哈哈哈。。。
    luckwang
        21
    luckwang  
       2014-02-19 14:54:29 +08:00
    用for的话有个enumerate()
    sandtears
        22
    sandtears  
       2014-02-19 14:57:54 +08:00
    因为作者不喜欢
    BOYPT
        23
    BOYPT  
       2014-02-19 15:04:27 +08:00   1
    在python里面找编码效率问题,你还真是找对了地方。
    davidli
        24
    davidli  
       2014-02-19 15:49:16 +08:00
    上面那个stackoverflow链接里的回答很有道理。
    i++平时就主要用在for语句里,而在Python里for语句直接用range()了,i++ ++i这种不够直观又容易出错的用法就没必要出现了。
    oldcai
        25
    oldcai  
    PRO
       2014-02-19 15:56:03 +08:00
    @est 是啊,我也是用的这个方法实现原先需要switch的功能。
    比起switch,这个不用只拘泥于数字类型。
    至于效率,都用脚本了,就不要那么计较了吧(啊喂,为什么不用ruby用python(找骂))。
    而且,到计较switch不满足条件会遍历条件的效率的时候,也会有其他的实现方式了。
    qazwsxedc121
        26
    qazwsxedc121  
       2014-02-19 16:07:46 +08:00
    我现在写js都绝对不写 ++ ,写 += 1 了,蝴蝶书里面说的我感觉很有道理
    FrankFang128
        27
    FrankFang128  
       2014-02-19 16:19:51 +08:00
    令人误解,不用也罢。
    liubin
        28
    liubin  
       2014-02-19 16:55:20 +08:00
    @VYSE 不加锁没有哪种语言会把++作为原子操作去实现吧。
    jiang42
        29
    jiang42  
       2014-02-19 17:12:49 +08:00
    每种语言都有各自的优劣
    想要自增自减大可以用C
    程序是写给人看的,不过计算机恰好能读懂而已
    BTW,python 是社区在进行开发,你可以去提出 issue 叫他们增加自增自减
    有没人愿意这么做就不知道了-。-
    kunimi
        30
    kunimi  
       2014-02-19 17:44:45 +08:00   1
    @yegle 这个例子还是有一定误导性的,对于整型变量来说,python其实定义了一个小整数池(-5到257),在这个范围内,如果对两个变量赋值同一个值,那么它们指向的是同一个对象。
    In [1]: i=258

    In [2]: j=258

    In [3]: id(i)
    Out[3]: 42930796

    In [4]: id(j)
    Out[4]: 42932492
    luoqeng
        31
    luoqeng  
       2014-02-19 18:21:46 +08:00
    @chevalier
    A (false) folk myth is that the instruction set architecture of the PDP-11 influenced the idiomatic use of the B programming language. The PDP-11's increment and decrement addressing modes correspond to the i and i++ constructs in C. If i and j were both register variables, an expression such as *(i) = *(j++) could be compiled to a single machine instruction. Dennis Ritchie unambiguously contradicts this folk myth, noting that the PDP-11 did not yet exist at the time of B's creation. He notes however that these addressing modes may have been suggested by the auto-increment cells of the PDP-7, though the implementation of B did not utilize this hardware feature.[4] The C programming language did however take advantage of several low level PDP-11 dependent programming features, resulting in the propagation of these features into new processors.

    http://en.wikipedia.org/wiki/PDP-11_architecture

    《C专家编程》里面好像也有讲
    jakwings
        32
    jakwings  
       2014-02-19 18:33:51 +08:00
    我觉得看完上面的所有评论才应该菊花一紧……不敢玩 Python 代码风格了怎么办?@est
    est
        33
    est  
       2014-02-19 19:06:46 +08:00
    @liubin 也不绝对。x86指令集支持这个 http://en.wikipedia.org/wiki/Fetch-and-add
    wodemyworld
        34
    wodemyworld  
       2014-02-19 19:11:31 +08:00
    没原生swith这个确实一开始不太能习惯
    VYSE
        35
    VYSE  
       2014-02-19 20:12:45 +08:00
    @liubin INC寄存器是原子的,要原子INC内存里一变量就得LOCK INC/DEC在X86,GCC里得用atomic系列函数搞,不知道其他编译器怎么选择
    workaholic
        36
    workaholic  
       2014-02-19 20:33:44 +08:00 via Android
    概念不同,python中数字和字符都是改变后就变了地址,前后加减操作给人错觉就是没有变地址
    weakish
        37
    weakish  
       2014-02-19 20:41:37 +08:00
    Lua里面连`+=`也没有……
    picasso250
        38
    picasso250  
       2014-02-20 09:42:34 +08:00
    there is one way to do one thing
    yegle
        39
    yegle  
       2014-02-20 11:00:28 +08:00
    另外,真的不试试enumerate函数吗…
    fghzpqm
        40
    fghzpqm  
       2014-02-20 11:25:42 +08:00
    @VYSE GIL 并不能保证 a += 1 是原子的。 cc @est
    VYSE
        41
    VYSE  
       2014-02-20 16:25:53 +08:00
    @fghzpqm 恩,GIL的确不行,itertools.count应该可以thread safe
    biby
        42
    biby  
       2016-03-07 19:15:31 +08:00
    好奇,先跟随写法,以后再思考
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1371 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 17:04 PVG 01:04 LAX 10:04 JFK 13:04
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86