2010-12-07 3 views
14

я столкнулся с чем-то интересное о питона дополненной назначении +=Python дополненной вопрос о назначении

это, кажется, автоматическое преобразование типов данных не всегда делается для a += b, если это «проще» тип данных, в то время как a = a + b кажется, работа всегда

случаев, когда преобразование выполняется

a = 1 
b = 1j 

a = 1 
b = 0.5 

случая, когда преобразование не сделано

from numpy import array 
a = array([0, 0 ,0]) 
b = array([0, 0, 1j]) 

после a += b, a остается целочисленной матрицы, вместо комплексной матрицы

я использовал думать a += b такой же, как a = a + b, в чем разница их в основной реализации?

+0

Что означает 'массив' в вашем примере? Это из встроенного модуля 'array'? если это так, ваш пример даже не работает, поскольку нет typecode ... – SingleNegationElimination

+0

'a = array ([0, 0, 0])' и 'b = array ([0, 0, 1j])' don ' t работать с классом 'array' в модуле с тем же именем. Они оба не имеют начального аргумента * typecode *. И, AFAIK, класс не поддерживает сложные числа, а '+ =' расширенное назначение. Поэтому я не понимаю, что вы просите здесь. – martineau

+0

@martineau См. Мой комментарий к отвечу Rafe (теперь удален.), Ссылаясь на этот вопрос NumPy: http://www.scipy.org/FAQ#head-1ed851e9aff803d41d3cded8657b2b15a888ebd5 – ACoolie

ответ

15

Для оператора +, Python определяет три "специальных" методов, что объект может реализовывать:

  • __add__: добавляет два элемента (+ оператора). Когда вы делаете a + b, метод __add__a вызывается с b в качестве аргумента.
  • __radd__: отражение добавить; для a + b, метод __radd__b в качестве примера вызывается a. Это используется только тогда, когда a не знает, как сделать добавление, и два объекта являются разными типами.
  • __iadd__: на месте добавить; используется для a += b, где результат присваивается левой переменной. Это предоставляется отдельно, потому что можно было бы реализовать его более эффективным образом. Например, если a - это список, то a += b совпадает с a.extend(b). Однако в случае c = a + b вам необходимо сделать копию a, прежде чем продлить ее, так как a не подлежит изменению в этом случае. Обратите внимание: если вы не реализуете __iadd__, тогда Python просто вызовет __add__.

Так, так как эти различные операции выполняются с отдельными методами, можно (но, как правило плохой практика) реализовать их так, что они делают совершенно разные вещи, или, возможно, в этом случае, только слегка разных вещей.

Другие пришли к выводу, что вы используете NumPy и объяснили его поведение. Однако вы спросили об основной реализации. Надеюсь, вы сейчас увидите , почему иногда бывает, что a += b - это не то же самое, что и a = a + b. Кстати, аналогичное трио методов также может быть реализовано для других операций. См. this page для получения списка всех поддерживаемых методов на месте.

+1

Я должен отметить, что в примере, который я дал для списков, 'a + = b' действительно имеет разные результаты от' a = a + b'. Если 'a' известно другим именем, это другое имя будет« видеть »расширенный список после' a + = b', но не после 'a = a + b'. – kindall

0

Ответ Rafe Kettler правильный, но, похоже, вам удалось получить a = [0,0,0] после добавления его в b (согласно вашему сообщению).

Ну, если вы используете NumPy или SciPy (я говорю об этом, потому что я вижу array и интересно, что массив создается здесь), то это «нормально», и должен даже поднять предупреждение:

ComplexWarning: Кастинг комплексных значений для реального выброса мнимой части

1

разницы между a = a + b и a += b в том, что последнее дополнение будет, по возможности, сделать «на месте», что означает, что при смене объекта a. Вы можете легко увидеть это со списками.

a = b = [1, 2] 
a += [3] 
print b # [1, 2, 3] 
a = b = [1, 2] 
a = a + [3] 
print b # [1, 2] 
+0

Да, и в случае массивов numpy это означает сохранение типа 'a' одинаковым, поэтому сложные числа не будут представлены. – tkerwin

7

Если array является numpy.array (вы на самом деле не указывать), то вопрос, что происходит, потому что эти массивы не могут изменить их тип. Когда вы создаете массив без спецификатора типа, он угадывает тип. Если вы затем попытаетесь выполнить операцию, тип которой не поддерживается (например, добавление ее к типу с более крупным доменом, например, сложный), numpy знает выполнение вычисления, но он также знает, что результат может быть сохранен только в типе с более крупным доменом. Он жалуется (на моей машине, во всяком случае, в первый раз, когда я выполняю такое задание), что результат не подходит. Когда вы делаете регулярное добавление, в любом случае должен быть создан новый массив, а numpy - правильный тип.

>>> a=numpy.array([1]) 
>>> a.dtype 
dtype('int32') 
>>> b=numpy.array([1+1j]) 
>>> b.dtype 
dtype('complex128') 
>>> a+b 
array([ 2.+1.j]) 
>>> (a+b).dtype 
dtype('complex128') 
>>> a+=b 
>>> a 
array([2]) 
>>> a.dtype 
dtype('int32') 
>>> 
Смежные вопросы