2010-07-17 41 views
3

我想知道什么是越来越分配给什么线8这个Python程序中发生了什么?

# 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 

节目我真的不需要太多的解释的其余部分。我不知道什么是分配给什么。

回答

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”这样的赋值现在就是合法的。 )
+0

然后很简单。感谢澄清。 – jimmyc3po 2010-07-17 20:17:02

+3

这会导致'self.b'乘以2,而不是两个变量的总和。 – 2010-07-17 20:19:21

+1

正确。如果2行按顺序执行,错误的事情会发生。我在我的回答中简要解释了这一点,马克·比尔斯在他的详细解释中解释了这一点 – 2010-07-17 20:24:05

3

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

它转换为等价的:

a = b 
b = a + b 

...从而计算该序列中的下一个号码。

如果你看看数字像

1 1 2 3 5 8 13 21 ... 

序列,你让ab是最后两个数字,那么以后你就必须在B和前最后一个数字(二的下一个号码) 在一个。

使用奇怪符号的原因是为了同时完成两个任务。如果它们按照上述2行顺序完成,则a的值将在第一行中被破坏,而第二行中的b会加倍。

8

这是一个多重分配大致相当于此:

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

还是这个伪代码:

 
a' = b 
b' = a + b 

正如你所看到的多重分配比单独的任务更加简洁,更加紧密类似于伪代码示例。

几乎在Python documentation中给出了这个例子,作为计算斐波那契数的一个例子。多重赋值的一个优点是,在任何赋值发生之前,右边的变量都会被赋值,在这种情况下可以节省临时变量的需要。

+0

首先,我想感谢你指点我的Python文档链接。这导致我只需要真正理解Fibonacci数字如何“循环”并打印出来的地方。我现在看到它是如何完成的,我对它更好。 此外,我不确定我是否可以投票你们三个人。如果我不能,这是一种遗憾,因为你们都配得上它,我会试着......等等...... – jimmyc3po 2010-07-17 21:08:30

+0

我问了关于这个计划的另一个问题,杰克,但是如果你有时间,它会很棒不止一个答复。如果你有时间的话。再次感谢以前的解释。 – jimmyc3po 2010-07-17 21:27:28

+0

难道我不能像第9行一样轻松地将'self.b'替换为'return self.a',它仍然是相同的“有效”程序?它输出相同的数字,只是好奇而已。 – jimmyc3po 2010-07-17 21:29:16

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. 既然已经分配了左元组的两个变量,就删除这两个元组。新的变量与他们的新价值保持一致。

因此,举例来说,你可以这样做:

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

还有引擎盖下参与临时变量,但你,程序员,不必处理它们。

+1

我不确定你在哪里得到你的想法,但你可能想了解更多关于Python变量的知识。 – SilentGhost 2010-07-18 13:30:54

+0

如果我写的是错的,我会删除它。你说这是错的吗? – eje211 2010-07-18 15:09:31