Изменяемые объекты в Python, копии и ссылки: как обнаружить проблему?

Пожалуйста, скажите мне, если то, что я пишу, правильно, и если вы можете ответить на мой вопрос в конце, я очень рад:

Верно ли, что переменные, назначенные спискам в python, являются "ссылками"? И то же самое справедливо для других изменяемых объектов (например, dict, но не кортежей)?

 a = [1,2,3]
 b = a
 def app(l,e):
     l += [ e ]

 app(a,5)
 print b

дает

 [1,2,3,5]

для того, чтобы иметь назначение по значению, а не по ссылке, я должен использовать deepcopy (из копии)?

Проблема для меня в том, что очень легко вносить ошибки, не обращая на это внимания! Итак, я заявляю следующее

ВОПРОС: есть ли инструмент статического анализа (например, pylint или что-то подобное), который может выдавать предупреждение для таких строк, как b = a или же app(a,5) сказать мне, что я потенциально изменяю свои изменяемые объекты (списки, словари)?

Спасибо

0 ответов

Я прочитал ссылку на вопрос в комментариях под названием "Как передать переменную по ссылке?" и некоторая документация. Я считаю, что обычные назначения Python и передача параметров технически передаются по значению. Однако каждое присвоение в Python автоматически запускает создание ссылки на объект. Когда вы назначилиa к b и прошел a в качестве параметра вашей функции обе строки кода инициировали создание ссылок на объект a. Затем ссылки были переданы в качестве значений вашей функции иb.

К сожалению, я не знаю ни одного инструмента статического анализа, который предупреждал бы вас об этих правилах. Я признаю, что они сбивают с толку, но единственное решение, которое я знаю, - это прочитать документацию и попытаться проверить концепции, используя простые фрагменты кода. Ваш код - хороший пример, из которого вы можете вывести "правила" Python и возможные проблемы.

В разделе документации Python говорится:

"... аргументы в Python передаются путем присваивания. Поскольку присваивание просто создает ссылки на объекты..."

Далее, согласно ответу на вопрос "Как передать переменную по ссылке?",

Если вы передаете изменяемый объект в метод, метод получает ссылку на тот же объект, и вы можете изменить его к своему удовольствию, но если вы повторно привяжете ссылку в методе, внешняя область ничего не будет знать об этом, а после все готово, внешняя ссылка по-прежнему будет указывать на исходный объект.

В вашем коде l += e выглядит как "повторное связывание" внутри метода и не должно изменяться a. Однако можно сделать вывод, что Python рассматривал+= [e] похожий на .append(e). Было указано, что "повторное связывание" переменной функции, которой был передан параметр вне области видимости, не должно влиять на переданный объект; несмотря на это,a был изменен l += [e]. Таким образом, можно сделать вывод, что Python не лечил+= []как переплет. Я призываю других также добавлять ссылки через комментарии в случае появления новой информации или исправлений.


ПРИМЕЧАНИЕ: может быть полезно использовать Pythonid()функция от переменной. Он показывает целое число, которое Python присваивает для идентификации объекта на протяжении "времени жизни" объекта. К сожалению, я не знаю точного определения понятия "время жизни". Вам лучше спросить других или прочитать документацию: встроенная функция Python id()

Другие вопросы по тегам