Почему делает + =, неожиданно ведут себя в списках?

При определении оси X вы можете изменить его, добавив в него «Тип» и установить значение «категория». По умолчанию библиотека просматривает данные, пытаясь определить тип для вас, если он не указан. Вот как должны выглядеть ваши изменения:

JFIDDLE : http://jsfiddle.net/xa1uy5dz/

[110 ]

Справочная информация: https://plot.ly/javascript/reference/#layout-xaxis-type

103
задан Eric Leschinski 20 February 2015 в 19:10
поделиться

4 ответа

>>> a = 89
>>> id(a)
4434330504
>>> a = 89 + 1
>>> print(a)
90
>>> id(a)
4430689552  # this is different from before!

>>> test = [1, 2, 3]
>>> id(test)
48638344L
>>> test2 = test
>>> id(test)
48638344L
>>> test2 += [4]
>>> id(test)
48638344L
>>> print(test, test2)  # [1, 2, 3, 4] [1, 2, 3, 4]```
([1, 2, 3, 4], [1, 2, 3, 4])
>>> id(test2)
48638344L # ID is different here

Мы видим, что, когда мы пытаемся изменить неизменный объект (целое число в этом случае), Python просто дает нам другой объект вместо этого. С другой стороны, мы можем внести изменения в изменяемый объект (список) и иметь его остаются тем же объектом повсюду.

касательно: https://medium.com / tyastropheus/tricky-python-i-memory-management-for-mutable-immutable-objects-21507d1e5b95

Также относятся ниже URL для понимания shallowcopy и deepcopy

https://www.geeksforgeeks.org/copy-python-deep-copy-shallow-copy /

0
ответ дан 24 November 2019 в 04:17
поделиться

Для общего случая см. ответ Скотта Гриффита . Однако при работе со списками, как вы, оператор + = является сокращением для someListObject.extend (iterableObject) . См. документацию по extend () .

Функция extend добавит все элементы параметра в список.

Выполняя foo + = something , вы изменяете список foo на месте, таким образом, вы не меняете ссылку, на которую указывает имя foo на, но вы изменяете объект списка напрямую. Используя foo = foo + something , вы фактически создаете новый список.

Этот пример кода объясняет это:

>>> l = []
>>> id(l)
13043192
>>> l += [3]
>>> id(l)
13043192
>>> l = l + [3]
>>> id(l)
13059216

Обратите внимание, как ссылка изменяется, когда вы переназначаете новый список на l .

Поскольку bar является переменной класса, а не переменной экземпляра, изменение на месте повлияет на все экземпляры этого класса. Но при переопределении self.bar экземпляр будет иметь отдельную переменную экземпляра self.bar , не затрагивая другие экземпляры класса.

89
ответ дан 24 November 2019 в 04:17
поделиться

Общий ответ таков: + = пытается вызвать специальный метод __ iadd __ , и если это недоступен, он пытается использовать вместо этого __ add __ . Итак, проблема в различии этих специальных методов.

Специальный метод __ iadd __ предназначен для добавления на месте, то есть он изменяет объект, на который действует. Специальный метод __ add __ возвращает новый объект и также используется для стандартного оператора + .

Итак, когда оператор + = используется для объекта, для которого задано значение __ iadd __ , объект изменяется на месте. В противном случае вместо этого он попытается использовать простой __ add __ и вернет новый объект.

Вот почему для изменяемых типов, таких как списки + = , изменяется значение объекта, тогда как для неизменяемых типов, таких как кортежи, строки и целые числа, вместо этого возвращается новый объект ( a + = b становится эквивалентным a = a + b ).

Для типов, поддерживающих как __ iadd __ , так и __ add __ , вы должны быть осторожны с тем, какой из них используете. a + = b вызовет __ iadd __ и изменит a , тогда как a = a + b создаст новый объект и назначит его a . Это не одна и та же операция!

>>> a1 = a2 = [1, 2]
>>> b1 = b2 = [1, 2]
>>> a1 += [3]          # Uses __iadd__, modifies a1 in-place
>>> b1 = b1 + [3]      # Uses __add__, creates new list, assigns it to b1
>>> a2
[1, 2, 3]              # a1 and a2 are still the same list
>>> b2
[1, 2]                 # whereas only b1 was changed

Для неизменяемых типов (где у вас нет __ iadd __ ) a + = b и a = a + b эквивалентны. Это то, что позволяет вам использовать + = для неизменяемых типов, что может показаться странным дизайнерским решением, пока вы не поймете, что в противном случае вы не могли бы использовать + = для неизменяемых типов, таких как числа!

113
ответ дан 24 November 2019 в 04:17
поделиться

Проблема в том, что bar определяется как атрибут класса, а не как переменная экземпляра.

В foo атрибут класса изменен в методе init , поэтому затрагиваются все экземпляры.

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

«Правильная» реализация:

class foo:
    def __init__(self, x):
        self.bar = [x]

Конечно, атрибуты класса полностью допустимы. Фактически, вы можете получить к ним доступ и изменить, не создавая экземпляр класса следующим образом:

class foo:
    bar = []

foo.bar = [x]
22
ответ дан 24 November 2019 в 04:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: