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
Eyon
V2EX  ›  Python

始终想不明白 a, b = b, a + b 到底是怎么工作的?

  •  
  •   Eyon · 2018-05-18 17:39:35 +08:00 · 4056 次点击
    这是一个创建于 2141 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如下例:

    class Fib(object):
        def __getitem__(self, n):
            a, b = 1, 1
            for x in range(n):
                a, b = b, a + b
            return a,b
    
    f = Fib()
    
    print(f[0])
    
    

    输出为什么是(1,1),而不是( 1,2 )?后面那个 1 到底是怎么产生的?

    15 条回复    2018-05-20 16:36:21 +08:00
    kenorizon
        1
    kenorizon  
       2018-05-18 17:42:38 +08:00 via iPhone
    list(range(0)) == []
    mofe
        2
    mofe  
       2018-05-18 17:42:47 +08:00
    for x in range(0) ,所以后面的赋值语句没有跑。。。
    IanPeverell
        3
    IanPeverell  
       2018-05-18 17:43:02 +08:00
    a, b = b, a+b
    完成的工作相当于
    c = a
    a = b
    b = c+b
    wellsc
        4
    wellsc  
       2018-05-18 17:43:22 +08:00
    后面那个 1 难道不是你自己赋值的?
    ```python
    a, b = 1, 1
    ```

    range(0) 的结果就是空列表好嘛?根本没有跑进循环体啊

    ``` python
    >>> for i in range(0):
    ... print('进来了吗')
    ...
    >>> print(range(0))
    []
    >>>
    ```
    Eyon
        5
    Eyon  
    OP
       2018-05-18 17:57:44 +08:00
    @wellsc
    @mofe

    0 基础初学 python,可能有些理解欠缺,照你们这么说,我对 for 循环的理解有误?

    拿 for x in range(3)举例,x 会分别赋值 0,1,2,也就是它会运行 3 次。
    第一次:
    a,b = b,a+b ---->(1,2)
    第二次:
    a,b = b,a+b ---->(2,3)
    第三次:
    a,b = b,a+b ---->(3,5)

    那么,f[0]不是取第一次运算后的结果么?
    gnaggnoyil
        6
    gnaggnoyil  
       2018-05-18 17:59:24 +08:00
    @Eyon `f[0]`等于`f.__getitem__(0)`...
    mofe
        7
    mofe  
       2018-05-18 18:03:07 +08:00
    @Eyon 额,我们来数个数

    range(3) 会赋值 0 1 2
    range(2) 会赋值 0 1
    range(1) 会赋值 0
    range(0) 呢?
    Eyon
        8
    Eyon  
    OP
       2018-05-18 18:06:11 +08:00
    @mofe

    [/捂脸][/捂脸][/捂脸],恍然大悟!

    f[0]不是取第一次运算的结果,而是取 n=0 时的结果,这么简单的逻辑,思考了两个下午都没思考透哈哈哈。
    Nostalgiaaaa
        9
    Nostalgiaaaa  
       2018-05-18 18:56:56 +08:00
    a, b = b, a+b
    这个其实是元组赋值了,python 会自动把右边这种用逗号分开的格式作为元组, 例如:
    >>> a = 1, 2
    >>> type(a)
    <class 'tuple'>
    >>> c, d = a
    >>> c, d
    (1, 2)
    也就是这个语句大概上就是个语法糖, 右边是多个值赋值, 左边是元组。
    F1024
        10
    F1024  
       2018-05-18 19:38:18 +08:00
    你至少要给 n 赋个值吧
    PythonAnswer
        11
    PythonAnswer  
       2018-05-18 19:42:18 +08:00 via iPhone
    Fib 一般有个 if 吧
    OldPanda
        12
    OldPanda  
       2018-05-19 05:29:00 +08:00
    把这个 Fib 类转换成字节码可以看到,for 循环内部是这个样子的
    5 22 LOAD_FAST 3 (b)
    24 LOAD_FAST 2 (a)
    26 LOAD_FAST 3 (b)
    28 BINARY_ADD
    30 ROT_TWO
    32 STORE_FAST 2 (a)
    34 STORE_FAST 3 (b)
    36 JUMP_ABSOLUTE 18
    >> 38 POP_BLOCK

    可以看到按照 b, a, b 的顺序压栈,然后对栈顶的两个元素进行相加(即 a + b ),然后分别存到 b, a (这里故意写反,因为中间有一个 ROT_TWO 操作)。所以说白了,Python 先把 b, a + b 的值分别准备好,再依次交给原有的 a, b。
    pmispig
        13
    pmispig  
       2018-05-19 15:11:25 +08:00
    这样写的是傻逼
    opengps
        14
    opengps  
       2018-05-19 17:58:51 +08:00 via Android
    true 可以用 1 表示
    AlisaDestiny
        15
    AlisaDestiny  
       2018-05-20 16:36:21 +08:00
    for x in range(3) 你知道是运行 3 次,那 for x in range(0) 是运行 1 次?是你犯糊了还是我犯糊了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   4013 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 10:19 · PVG 18:19 · LAX 03:19 · JFK 06:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.