2010-07-17 3 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

+3

Это приведет к тому, что 'self.b' будет умножен на 2, а не будет суммой двух переменных. –

+1

Исправить. Если две строки были выполнены последовательно, произойдет неправильное. Я коротко объяснил это в своем ответе и Марк Байерс более подробно в своем. –

3

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

Это переводит на эквивалент:

a = b 
b = a + b 

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

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

1 1 2 3 5 8 13 21 ... 

и вы позволяете a и 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. Это привело меня к тому месту, которое мне нужно, чтобы по-настоящему понять, как числа Фибоначчи «зацикливаются» и распечатываются. Теперь я вижу, как это делается, и мне гораздо лучше. Кроме того, я не уверен, могу ли я проголосовать за всех вас троих. Если я не могу, это позор, потому что вы все это заслуживаете, я собираюсь попробовать ... и т. Д. – jimmyc3po

+0

Я задал еще один вопрос относительно этой программы t Jack, но если у вас есть время, было бы здорово получить более одного ответа. Если у вас есть время. Еще раз спасибо за более раннее объяснение. – jimmyc3po

+0

Не мог бы я так же легко на Line 9 поставить 'return self.b' вместо 'return self.a', и все равно будет такая же «действительная» программа? Он выводит одинаковый номер, просто любопытно, что это все. – jimmyc3po

0

Помните, что сопряженное присваивание не является «особенностью» 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

+0

Если я написал неправильно, я удалю его. Вы говорите, что это неправильно? – eje211