Что происходит в этой программе Python? - PullRequest
3 голосов
/ 18 июля 2010

Я хотел бы знать, что назначается на что в строке 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 ]

8 голосов
/ 18 июля 2010

Это множественное назначение, примерно эквивалентное этому:

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

Или этот псевдокод:

a' = b
b' = a + b

Как вы видите, множественное назначение гораздо более сжато, чем отдельные назначенияи более близко напоминает пример псевдокода.

Почти этот пример приведен в документации Python как пример вычисления чисел Фибоначчи.Одним из преимуществ множественного присвоения является то, что переменные с правой стороны оцениваются до того, как произойдет любое из присвоений, сохраняя в этом случае необходимость во временной переменной.

7 голосов
/ 18 июля 2010

Это парное назначение, сокращение

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", теперь допустимо, если строка имеет правильную длину. )
3 голосов
/ 18 июля 2010

Не глядя на окружающий код, я бы сказал, что это сердце алгоритма для вычисления чисел Фибоначчи.

Это соответствует эквиваленту:

a = b
b = a + b

...тем самым вычисляя следующие числа в последовательности.

Если вы посмотрите на последовательность чисел типа

1 1 2 3 5 8 13 21 ...

, и вы позволите a и b быть последними двумячисла, затем после этого у вас будет следующий номер в b и предыдущий последний номер (b) в a.

Причина использования этой странной записи состоит в том, чтобы выполнить оба назначения одновременно.Если бы они были выполнены последовательно, как в 2 строках выше, значение a было бы засорено в первой строке, и вы бы просто удвоили b во 2-й строке.

0 голосов
/ 18 июля 2010

Имейте в виду, что парное назначение не является «особой функцией» 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)

Все еще существуют временные переменные, но вы, программист, не должны иметь с ними дело.

...