Важная концепция программирования, которую часто упускают из виду в курсах и руководствах, которые формально не являются «информатикой».
Понимание изменчивости объектов — важная концепция, которая почти наверняка будет рассмотрена на уроках информатики или в учебном лагере. Тем не менее, его часто упускают из виду на тренингах, посвященных науке о данных, статистике, пользовательскому опыту, биоинженерии или любой другой связанной области, где каким-то образом используется код.
Это проблема, поскольку это важная концепция, которая влияет на то, как программист пишет и разрабатывает код. Неправильное понимание или неосведомленность о том, как работает изменчивость, может привести к запутанным ошибкам или даже кажущемуся работающему коду, который впоследствии сломается.
В этой статье я представлю обзор изменчивости вместе с некоторыми подробными примерами.
Что такое изменчивость?
С точки зрения технического программирования, изменяемый объект — это объект, состояние которого может быть изменено после его определения. Противоположностью изменяемого объекта является неизменяемый объект, состояние которого нельзя изменить после того, как он был первоначально определен.
Примеры неизменяемых объектов в Python включают целые числа, числа с плавающей запятой, строки и кортежи. Два типа изменяемых объектов, с которыми вы, вероятно, чаще всего будете иметь дело при программировании на Python, — это списки и словари.
Давайте рассмотрим конкретный пример разницы между изменчивостью и неизменностью. Скажем, я определяю список песен. Если я хочу изменить список, заменив одну из песен, это прекрасно, потому что списки изменяемы:
>>> my_songs = ["All Too Well", "No Tears Left to Cry", "Cruel Summer"] >>> my_songs[1] = "Champagne Problems" >>> my_songs ['All Too Well', 'Champagne Problems', 'Cruel Summer']
Напротив, предположим, что я определяю строку, которая является неизменяемым объектом, но случайно написал ее с ошибкой. Если я затем попытаюсь изменить строку, Python жалуется:
>>> my_song = "All Too Wall" >>> my_song[9] = 'e' Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'str' object does not support item assignment
После определения строки ее содержимое нельзя изменить. Мне нужно будет определить новую строку, если я хочу исправить правописание.
Если вы подумаете о функциональности списков и словарей, вы поймете, что все это время пользовались их изменчивостью, даже если вы этого не осознавали. Такие функции, как append
, extend
и update
, изменяют список или словарь, на который они ссылаются, и могут быть очень полезны для отслеживания данных или выполнения определенной задачи программирования.
Однако, хотя изменяемые объекты могут быть полезны в некоторых случаях, они часто могут привести к ошибкам, если программист не знает, как они работают внутри. В следующем разделе я исследую подробный пример, чтобы объяснить, что может пойти не так, если неправильно понять изменчивость.
Подробный пример того, почему это важно
В этом разделе я напишу две функции — одну, которая работает с целым числом, и одну, которая работает со списком. Исследуя вывод каждой функции и объясняя, что происходит за кулисами, я покажу, почему нужно быть осторожным при работе с изменяемыми объектами.
Первая функция добавляет число 6
к целому числу, а вторая функция добавляет число 6
к списку:
# Add 6 to a number def addnum
to_number(num): num = num + 6 # Append 6 to the end of a list def appendnum
to_list(lst): lst.append(6)
Теперь я напишу короткий фрагмент кода, используя описанные выше функции. Обратите особое внимание на значения начальных целых и списочных переменных до и после вызова функций:
>>> num = 10 >>> addnum
to_number(num) >>> print(num) # num remains unchanged 10 >>> list_num = [10] >>> appendnum
to_list(list_num) >>> print(list_num) # list_num, however, changes [10, 6]
Лично я нашел это увлекательным, когда впервые узнал об этом. Переменная num
остается неизменной, а переменная list_num
изменяется. Почему это происходит? Это связано с тем, как изменяемые объекты передаются в функцию. Это легче увидеть визуально.
Ниже я скопировал три изображения из Python Tutor, отличного онлайн-инструмента, который может помочь вам визуализировать ваш код Python. Они показывают, что происходит под капотом до, во время и после того, как я вызову функцию add_6_to_num
.
Ключевым наблюдением здесь является то, что при вызове add_6_to_num
создается копия переменной num
, и именно эта копия изменяется внутри функции. Но начальная переменная num
, которую мы определяем, остается неизменной вне функции. Это верно для всех неизменяемых объектов: когда они передаются в функцию, Python создает их копию.
Теперь давайте посмотрим на соответствующие три диаграммы для списка:
Видите принципиальную разницу? Поскольку списки изменяемы, Python не создает их копии при передаче в функцию. Таким образом, выше ссылка (представленная стрелкой) на тот же список передается в функцию append_6_to_list
. Переменная внутри и вне функции ссылается на один и тот же список, поэтому при ее изменении внутри функции значение переменной num_list
вне функции также меняется.
Это относится ко всем изменяемым объектам — когда они передаются в функцию, Python не будет делать их копию, а вместо этого просто передаст ссылку на уже существующий объект. Это то, о чем следует особенно помнить при написании кода, так как это сбивает с толку даже самых опытных программистов. Если в вашем коде есть куча ссылок на список, словарь или какой-либо другой изменяемый объект, это может вызвать много проблем и привести к неожиданным значениям.
Последние мысли
Поскольку наука о данных выросла на основе статистики, соответствующие учебные заведения по науке о данных иногда пренебрегают преподаванием важных концепций информатики. Однако это может привести к низкокачественному коду, который трудно поддерживать.
Списки и словари являются огромной частью науки о данных в Python — они обе представляют собой структуры данных, которые широко используются в модуле обработки данных Python Pandas. В результате важно понимать, как Python обрабатывает эти объекты при написании кода, который использует их и полагается на них. Знание концепций, изложенных в этой статье, было полезно для меня, и я надеюсь, что это может быть полезно и для вас.
До следующего раза, ребята!
Хотите преуспеть в Python? Получите эксклюзивный бесплатный доступ к моим простым и понятным руководствам здесь.
Пожалуйста, рассмотрите возможность использования моей реферальной ссылки ниже, чтобы зарегистрироваться в качестве полноправного участника Medium. Вы сможете читать неограниченное количество рассказов в месяц, а ваш членский взнос напрямую поддерживает меня и других писателей.