【问题标题】:What is happening in this Python program?这个 Python 程序发生了什么?
【发布时间】:2010-07-17 20:13:27
【问题描述】:

我想知道第 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

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

【问题讨论】:

    标签: python iterator variable-assignment


    【解决方案1】:

    这是一个大致相当于这个的多重赋值:

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

    或者这个伪代码:

    a' = b b' = a + b

    正如您所见,多重赋值比单独赋值要简洁得多,并且更类似于伪代码示例。

    Python documentation 中几乎给出了该示例,作为计算斐波那契数的示例。多重赋值的优点之一是右侧的变量在任何赋值发生之前都会被评估,在这种情况下不需要临时变量。

    【讨论】:

    • 首先,感谢您将我指向 Python 文档链接。这将我带到了真正了解斐波那契数字是如何被“循环”和打印出来的地方。我现在看到了它是如何完成的,而且我做得更好了。另外,我不确定我是否可以对你们三个人都投赞成票。如果我做不到,那就太可惜了,因为你们都应得的,我要试试……等等……
    • 我向 Jack 提出了另一个关于这个程序的问题,但如果你有时间,得到多个回复会很棒。如果你有时间。再次感谢您之前的解释。
    • 难道我不能在第 9 行轻松地放 'return self.b' 而不是 'return self.a' 并且它仍然是相同的“有效”程序吗?它输出相同的数字,只是好奇而已。
    【解决方案2】:

    这是一对赋值,是的简写

    t = self.a
    self.a = self.b
    self.b = t+self.b
    

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

    如文档所述:

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

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

    【讨论】:

    • 那么简单。感谢您的澄清。
    • 这将导致self.b 被乘以 2,而不是两个变量的总和。
    • 正确。如果这两行按顺序执行,就会发生错误的事情。我在回答中简要解释了这一点,Mark Byers 在他的回答中更详细地解释了这一点。
    • 感谢您对此的深入解释。你所有的答案都有帮助。但是因为你给出了如此好的和详细的解释,我想看看你是否会回答关于这个程序的另一个问题。 :) 我粘贴在paste.pocoo.org/show/238815 的程序不能像在第 9 行那样轻松地放置“return self.b”而不是“return self.a”,它仍然是相同的“有效”程序。它仍然输出相同的 1597,我认为(我可能会弄错)它也会少一次迭代吗?无论如何,第 9 行的“return self.b”同样有效,对吧?
    【解决方案3】:

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

    相当于:

    a = b
    b = a + b
    

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

    如果你看一个像这样的数字序列

    1 1 2 3 5 8 13 21 ...
    

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

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

    【讨论】:

      【解决方案4】:

      请注意,配对赋值不是 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)
      

      幕后仍然涉及临时变量,但你,程序员,不必处理它们。

      【讨论】:

      • 我不确定您的想法从何而来,但您可能想了解更多有关 Python 变量的信息。
      • 如果我写的有问题,我会删除它。你说错了吗?
      猜你喜欢
      • 2015-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-21
      • 1970-01-01
      • 1970-01-01
      • 2018-05-12
      • 1970-01-01
      相关资源
      最近更新 更多