在一行和几行上写东西之间的区别

时间:2015-12-03 15:16:27

标签: python

当我在一行上写东西时,区别在于,和两行。显然我不明白其中的区别,因为我虽然下面的两个函数应该返回相同的。

def fibi(n):
    a, b = 0, 1
    for i in range(n):
        a, b = b, a + b
    return a

print(fibi(6))
> 8 # expected result (Fibonacci)

但是

def fibi(n):
    a, b = 0, 1
    for i in range(n):
        a = b
        b = a + b 
    return a


print(fibi(6))
> 32 

6 个答案:

答案 0 :(得分:13)

这是因为Python的元组解包。在第一个中,Python收集右侧的值,使它们成为元组,然后将元组的值分别分配给左侧的名称。所以,如果a == 1且b == 2:

   a, b = b, a + b
=> a, b = (2, 3)
=> a = 2, b = 3

但是在第二个例子中,它是正常的分配:

   a = b
=> a = 2
   b = a + b
=> b = 4

答案 1 :(得分:2)

找到

的替代品
a, b = b, a + b

您必须意识到此分配是“一步一步”执行的。

所以它的等价物是

old_a = a
a = b
b = old_a + b # note the old_a here, as a has been replaced in the meanwhile.

演示:

def fibi(n):
    a, b = 0, 1
    for i in range(n):
        a, b = b, a + b
    return a

def fibi2(n):
   a, b = 0, 1
   for i in range(n):
    old_a = a
    a = b
    b = old_a + b
   return a

>>> fibi(0)
0
>>> fibi(1)
1
>>> fibi(2)
1
>>> fibi(3)
2
>>> fibi(4)
3
>>> fibi(5)
5
>>> fibi(6)
8
>>> fibi(7)
13
>>>
>>>
>>>
>>> fibi2(0)
0
>>> fibi2(1)
1
>>> fibi2(2)
1
>>> fibi2(3)
2
>>> fibi2(4)
3
>>> fibi2(5)
5
>>> fibi2(6)
8
>>> fibi2(7)

答案 2 :(得分:1)

你的不同之处在于:

1)

>>> a, b = 0, 1
>>> a, b = b, a+b
>>> a
1
>>> b
1

VS

2)

>>> a, b = 0, 1
>>> a = b
>>> b = a+b
>>> a
1
>>> b
2

在第一种情况下,a = 1b = 0 + 1在变量的值发生变化之前。您基本上是说“在给定状态X下使用(a,b),将(a,b)设置为值(0,1)。”

了解这些事情的不同之处的一个好方法是使用disassembly模块(按照链接查看代码含义):

>>> from dis import dis
>>> a, b = 0, 1
>>> dis('a, b = b, a+b')
  1           0 LOAD_NAME                0 (b)
              3 LOAD_NAME                1 (a)
              6 LOAD_NAME                0 (b)
              9 BINARY_ADD
             10 ROT_TWO
             11 STORE_NAME               1 (a)
             14 STORE_NAME               0 (b)
             17 LOAD_CONST               0 (None)
             20 RETURN_VALUE
>>> a, b = 0, 1
>>> dis('a = b; b = a+b')
  1           0 LOAD_NAME                0 (b)
              3 STORE_NAME               1 (a)
              6 LOAD_NAME                1 (a)
              9 LOAD_NAME                0 (b)
             12 BINARY_ADD
             13 STORE_NAME               0 (b)
             16 LOAD_CONST               0 (None)
             19 RETURN_VALUE

答案 3 :(得分:0)

不同之处在于,在第二个示例中,您在引用a之前将b设置为a。第二个示例中的值将关闭。这是一个例子:

a = 5
b = 6

实施例1,:

a, b = b, a+b // a = 6 and b = 11

例2:

a = b // a = 6
b = a + b // b = 6+6 or 12

第一个例子是正确的

答案 4 :(得分:0)

在第一种情况下,命令

a, b = b, a + b;

将首先执行总和a + b,然后执行分配。在这种情况下,b总是包含1.这解释了为什么最终结果是6,因为你要加6次。

您发布的第二个代码是正确的。

答案 5 :(得分:0)

Raymond Hettinger的完美解释可以在这个PyCon 2013视频中找到,时间是33:13到38:17:

https://www.youtube.com/watch?v=OSGv2VnC0go

引用他的演讲:

  
      
  • 不要低估同时更新状态变量的优势
  •   
  • 消除了由于无序更新导致的整类错误
  •