这个Python程序发生了什么?

时间:2010-07-17 20:13:27

标签: python iterator variable-assignment

我想知道第8行的内容是什么。

# Iterators

class Fibs:
    def __init__(self):
        self.a = 0
        self.b = 1
    def next(self):
        self.a, self.b = self.b, self.a+self.b # <--- here
        return self.a
    def __iter__(self):
        return self

fibs = Fibs()

for f in fibs:
    if f > 1000:
        print f
        break

程序的其余部分我真的不需要太多解释。我不确定是什么分配给了什么。

4 个答案:

答案 0 :(得分:8)

这是一个大致相当于此的多项任务:

tmp = self.a
self.a = self.b
self.b = tmp + self.b

或者这个伪代码:

a' = b
b' = a + b

正如您所看到的,多重分配比单独分配更简洁,更类似于伪代码示例。

几乎这个例子在Python documentation中给出,作为计算斐波纳契数的一个例子。多重赋值的一个优点是在任何赋值发生之前评估右侧的变量,在这种情况下节省了对临时变量的需求。

答案 1 :(得分:7)

这是一对配对,是

的简写
t = self.a
self.a = self.b
self.b = t+self.b

只是使用一行代替两个赋值..确切地说,我认为赋值的左操作数被认为是两个元素的元组,所以你就像赋值给元组(self.a, self,b)一样(self.b, self.a+self.b)与之前编写的三个单独的赋值完全相同,而不需要临时变量。这是因为,虽然不使用元组,但是按顺序执行赋值,在您的示例中,它们会同时被解析,在第二次赋值中保留self.a的值。

如文件中所述:

将对象分配给目标列表按递归方式定义如下。

  • 如果目标列表是单个目标:该对象将分配给该目标。
  • 如果目标列表是以逗号分隔的目标列表(您的案例):该对象必须是一个可迭代的项,其数量与目标列表中的目标相同,并且项目从左到右分配给相应的目标。 (从Python 1.5开始,此规则是放宽的;在早期版本中,对象必须是元组。由于字符串是序列,因此只要字符串具有正确的长度,类似a,b =“xy”的赋值现在是合法的。 )

答案 2 :(得分:3)

不看周围的代码,我会说这是计算斐波纳契数的算法的核心。

它转换为相当于:

a = b
b = a + b

...从而计算序列中的下一个数字。

如果你看一下像

这样的数字序列
1 1 2 3 5 8 13 21 ...

你让ab成为最后两个数字,然后你将获得b中的下一个数字和前一个最后一个数字(b)。

使用这种奇怪表示法的原因是为了同时完成两个作业。如果它们按顺序完成,如上面的2行中那样,a的值将在第一行中被破坏,而你只是在第二行中加倍b。

答案 3 :(得分:0)

请注意,配对分配不是Python的“特殊功能”。如果您对Python有所了解,那么您已经了解它,但您可能不知道。当您将以下内容放入python控制台时:

>>> 'a', 'b'

你得到的回报是:

('a', 'b')

换句话说,一个元组。在您的示例中,

self.a, self.b = self.b, self.a+self.b

你真正在做的是:

(self.a, self.b) = (self.b, self.a+self.b)
  1. 创建一个元组,其中包含self.b的值和self.a + self.b的值。 (右边的元组。)
  2. 创建一个包含self.a和self.b的元组。 (左手元组。)
  3. 为了创建左手元组,为该新元组创建一个新的self.a和self.b实例。他们的旧价值不再重要了:他们是临时的右手元组。
  4. 将左元组变量的值0分配给右元组的值0。
  5. 将左元组变量的值1分配给右元组的值1。
  6. 现在分配了左元组的两个变量,删除两个元组。新变量保留其新值。
  7. 因此,例如,你可以这样做:

    >>> a, b = 1, 2
    >>> a, b
    (1, 2)
    >>> a, b = b, a
    >>> a, b
    (2, 1)
    

    还有一些临时变量,但程序员不必处理它们。