Как поменять значение переменной используя функцию? Python
возникла необходимость поменять значение переменной используя функцию. Выглядеть это должно примерно так:
Возможно это как-либо сделать или единственное решение это:
![]()
В Python можно перезаписывать глобальные переменные таким образом
Если вы хотите перезаписать переменную по ее имени, как указано в вопросе то можно так
Но не понятно зачем так делать
Всё ещё ищете ответ? Посмотрите другие вопросы с метками python или задайте свой вопрос.
Site design / logo © 2022 Stack Exchange Inc; user contributions licensed under cc by-sa. rev 2022.6.10.42345
Нажимая «Принять все файлы cookie», вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.
Изменяемые и неизменяемые объекты в Python

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

Давайте углубимся в детали. Поскольку все в Python является объектом, то каждая переменная является экземпляром какого-то класса (объектом). Когда объект инстанцируется, ему присваивается уникальный id. Тип объекта определяется во время выполнения и после этого не меняется, однако состояние может меняться, если оно изменяемое. Проще говоря, изменяемый объект можно изменить после его создания, а неизменяемый – нет.
Объекты встроенных типов, таких как int, float, bool, str, tuple, unicode, являются неизменяемыми. Объекты встроенных типов, таких как list, set, dict, являются изменяемыми. Самописные классы, как правило, изменяемые. Если есть потребность сымитировать неизменяемость, нужно переопределить методы установки и удаления атрибутов класса так, чтобы они вызывали исключения.

Возникает вопрос, как узнать, что наша переменная изменяемый или неизменяемый объект. Для этого нам нужно понять, зачем нужны функции id и type.
Id() и type()
Встроенная функция id() возвращается id объекта в виде целого числа. Число обычно коррелирует с местоположением объекта в памяти, но не всегда, поскольку все зависит от реализации Python и используемой платформы. Оператор is сравнивает id двух объектов.
Встроенная функция type() возвращает тип объекта. Давайте обратимся к примеру.
Теперь мы знаем, как сравнить две простые строковые переменные, чтобы определить их тип и id. С помощью этих двух функций мы можем узнать типы объектов связанных с переменными и их изменяемость/неизменяемость.
Изменяемые и неизменяемые объекты
Итак, как мы выяснили, изменяемый объект может изменять свое состояние или содержимое, а неизменяемый – нет.
Изменяемые объекты:
list, dict, set, byte array
Неизменяемые объекты:
int, float, complex, string, tuple, frozenset (неизменяемая версия set), bytes
Пример определения изменяемости объекта:
Мы создаем объект типа int. Id x и y указывают на один и тот же объект:
А теперь просто прибавим единицу:
Объект переменной x изменился. Объект 10 не может изменяться. Неизменяемые объекты не допускают изменений после создания.
А если объект изменяемый:
Мы создаем объект типа list. Id переменных m и n привязаны к одному списку, в котором лежит коллекция из трех неизменяемых объектов типа int.
Удаление элемента из объекта списка изменяет сам объект:
Но id объекта не изменяется
Переменные m и n будут указывать на один и тот же объект списка после изменения. В объекте списка теперь лежит [1,2].
Итак, что же мы поняли из примеров выше?
Python обрабатывает изменяемые и неизменяемые объекты по-разному.
Доступ к неизменяемым объектам осуществляется быстрее, чем к изменяемым.
Изменяемые объекты отлично подойдут, если вам нужно менять размер объектов, например, list, dict и т.д.
Неизменяемые значения используются, когда вам нужно убедиться, что созданный вами объект никогда не будет меняться.
Неизменяемые объект принципиально дорого менять, поскольку для этого требуется создать копию, а изменяемые менять легко.
Исключения в неизменяемости
Не все неизменяемые объекты на самом деле являются неизменяемыми. Запутались? Позвольте мне объяснить.
Как мы говорили ранее, такие коллекции в Python, как кортежи, неизменяемы. То есть значение кортежа нельзя менять после его создания. Но значение кортежа на самом деле – это последовательность имен с неизменяемыми привязками к объектам. Главное, что нужно понимать, так это то, что сами «привязки» менять нельзя, а вот объекты на их концах – можно.
Рассмотрим кортеж t = (‘holberton’, [1, 2, 3])
Он содержит элементы разных типов данных, первый из которых – неизменяемая строка, а второй – изменяемый список. Сам со себе кортеж неизменяемый, то есть для него нет методов изменения содержимого. Строка также неизменяемая по той же причине. Но у списка есть такие методы, поэтому его можно изменить. Здесь тонкий момент, но не менее важный: «значение» неизменяемого объекта не может измениться, а вот его элементы могут.
Как объекты передаются в функции
Для нас важно знать разницу между изменяемыми и неизменяемыми типами, чтобы понимать, как они обрабатываются при передаче в функции. Эффективность использования памяти сильно зависит от выбора соответствующих объектов.
Например, если изменяемый объект вызывается по ссылке в функции, он может изменить исходную переменную. Следовательно, чтобы избежать этого, исходную переменную надо скопировать в другую переменную. Неизменяемые объекты можно передавать по ссылке, потому что их значение в любом случае не может меняться.
Как видно из примера выше, мы получили доступ к списку по ссылке, поэтому смогли изменить исходный список.
Давайте посмотрим на другой пример:
В примере выше в функцию передается один и тот же объект, но значение переменных не меняется даже если их id одинаковые. Так работает передача по значению. Что же здесь происходит? Когда функция вызывает значение, передается только значение переменной, а не сам объект. Таким образом, переменная, ссылающаяся на объект, не изменяется, а сам объект изменяется, но только в пределах области видимости функции. Следовательно, изменение не видно «снаружи».
16 мая в Otus состоится открытое занятие «Работа с сетью», на котором познакомимся с HTTP, кодами статусов, методами, типами ответа, а также с протоколом wsgi. В итоге мы поймем принципы работы HTTP, научимся различать методы и статус коды. Записаться можно здесь.
Python как изменить переменную через функцию
Напомним, что в математике факториал числа n определяется как Например, Ясно, что факториал можно легко посчитать, воспользовавшись циклом for. Представим, что нам нужно в нашей программе вычислять факториал разных чисел несколько раз (или в разных местах кода). Конечно, можно написать вычисление факториала один раз, а затем используя Copy-Paste вставить его везде, где это будет нужно.
Однако, если мы ошибёмся один раз в начальном коде, то потом эта ошибка попадёт в код во все места, куда мы скопировали вычисление факториала. Да и вообще, код занимает больше места, чем мог бы. Чтобы избежать повторного написания одной и той же логики, в языках программирования существуют функции.
Функции — это такие участки кода, которые изолированы от остальный программы и выполняются только тогда, когда вызываются. Вы уже встречались с функциями sqrt(), len() и print(). Они все обладают общим свойством: они могут принимать параметры (ноль, один или несколько), и они могут возвращать значение (хотя могут и не возвращать). Например, функция sqrt() принимает один параметр и возвращает значение (корень числа). Функция print() принимает переменное число параметров и ничего не возвращает.
Покажем, как написать функцию factorial(), которая принимает один параметр — число, и возвращает значение — факториал этого числа.
Дадим несколько объяснений. Во-первых, код функции должен размещаться в начале программы, вернее, до того места, где мы захотим воспользоваться функцией factorial(). Первая строчка этого примера является описанием нашей функции. factorial — идентификатор, то есть имя нашей функции. После идентификатора в круглых скобках идет список параметров, которые получает наша функция. Список состоит из перечисленных через запятую идентификаторов параметров. В нашем случае список состоит из одной величины n. В конце строки ставится двоеточие.
Далее идет тело функции, оформленное в виде блока, то есть с отступом. Внутри функции вычисляется значение факториала числа n и оно сохраняется в переменной res. Функция завершается инструкцией return res, которая завершает работу функции и возвращает значение переменной res.
Инструкция return может встречаться в произвольном месте функции, ее исполнение завершает работу функции и возвращает указанное значение в место вызова. Если функция не возвращает значения, то инструкция return используется без возвращаемого значения. В функциях, которым не нужно возвращать значения, инструкция return может отсутствовать.
Приведём ещё один пример. Напишем функцию max(), которая принимает два числа и возвращает максимальное из них (на самом деле, такая функция уже встроена в Питон).
Теперь можно написать функцию max3(), которая принимает три числа и возвращает максимальное их них.
2. Локальные и глобальные переменные
Внутри функции можно использовать переменные, объявленные вне этой функции
Здесь переменной a присваивается значение 1, и функция f() печатает это значение, несмотря на то, что до объявления функции f эта переменная не инициализируется. В момент вызова функции f() переменной a уже присвоено значение, поэтому функция f() может вывести его на экран.
Такие переменные (объявленные вне функции, но доступные внутри функции) называются глобальными.
Но если инициализировать какую-то переменную внутри функции, использовать эту переменную вне функции не удастся. Например:
Получим ошибку NameError: name ‘a’ is not defined . Такие переменные, объявленные внутри функции, называются локальными. Эти переменные становятся недоступными после выхода из функции.
Интересным получится результат, если попробовать изменить значение глобальной переменной внутри функции:
Будут выведены числа 1 и 0. Несмотря на то, что значение переменной a изменилось внутри функции, вне функции оно осталось прежним! Это сделано в целях “защиты” глобальных переменных от случайного изменения из функции. Например, если функция будет вызвана из цикла по переменной i , а в этой функции будет использована переменная i также для организации цикла, то эти переменные должны быть различными. Если вы не поняли последнее предложение, то посмотрите на следующий код и подумайте, как бы он работал, если бы внутри функции изменялась переменная i.
Более формально: интерпретатор Питон считает переменную локальной для данной функции, если в её коде есть хотя бы одна инструкция, модифицирующая значение переменной, то эта переменная считается локальной и не может быть использована до инициализации. Инструкция, модифицирующая значение переменной — это операторы = , += , а также использование переменной в качестве параметра цикла for . При этом даже если инструкция, модицифицирующая переменную никогда не будет выполнена, интерпретатор это проверить не может, и переменная все равно считается локальной. Пример:
Возникает ошибка: UnboundLocalError: local variable ‘a’ referenced before assignment . А именно, в функции f() идентификатор a становится локальной переменной, т.к. в функции есть команда, модифицирующая переменную a , пусть даже никогда и не выполняющийся (но интерпретатор не может это отследить). Поэтому вывод переменной a приводит к обращению к неинициализированной локальной переменной.
Чтобы функция могла изменить значение глобальной переменной, необходимо объявить эту переменную внутри функции, как глобальную, при помощи ключевого слова global :
В этом примере на экран будет выведено 1 1, так как переменная a объявлена, как глобальная, и ее изменение внутри функции приводит к тому, что и вне функции переменная будет доступна.
Тем не менее, лучше не изменять значения глобальных переменных внутри функции. Если ваша функция должна поменять какую-то переменную, пусть лучше она вернёт это значением, и вы сами при вызове функции явно присвоите в переменную это значение. Если следовать этим правилам, то функции получаются независимыми от кода, и их можно легко копировать из одной программы в другую.
Например, пусть ваша программа должна посчитать факториал вводимого числа, который вы потом захотите сохранить в переменной f. Вот как это не стоит делать:
Этот код написан плохо, потому что его трудно использовать ещё один раз. Если вам завтра понадобится в другой программе использовать функцию «факториал», то вы не сможете просто скопировать эту функцию отсюда и вставить в вашу новую программу. Вам придётся поменять то, как она возвращает посчитанное значение.
Гораздо лучше переписать этот пример так:
Если нужно, чтобы функция вернула не одно значение, а два или более, то для этого функция может вернуть список из двух или нескольких значений:
Тогда результат вызова функции можно будет использовать во множественном присваивании:
3. Рекурсия
Как мы видели выше, функция может вызывать другую функцию. Но функция также может вызывать и саму себя! Рассмотрим это на примере функции вычисления факториала. Хорошо известно, что 0!=1, 1!=1. А как вычислить величину n! для большого n? Если бы мы могли вычислить величину (n-1)!, то тогда мы легко вычислим n!, поскольку n!=n⋅(n-1)!. Но как вычислить (n-1)!? Если бы мы вычислили (n-2)!, то мы сможем вычисли и (n-1)!=(n-1)⋅(n-2)!. А как вычислить (n-2)!? Если бы. В конце концов, мы дойдем до величины 0!, которая равна 1. Таким образом, для вычисления факториала мы можем использовать значение факториала для меньшего числа. Это можно сделать и в программе на Питоне:
Подобный прием (вызов функцией самой себя) называется рекурсией, а сама функция называется рекурсивной.
- Неправильное оформление выхода из рекурсии. Например, если мы в программе вычисления факториала забудем поставить проверку if n == 0 , то factorial(0) вызовет factorial(-1) , тот вызовет factorial(-2) и т. д.
- Рекурсивный вызов с неправильными параметрами. Например, если функция factorial(n) будет вызывать factorial(n) , то также получится бесконечная цепочка.
Поэтому при разработке рекурсивной функции необходимо прежде всего оформлять условия завершения рекурсии и думать, почему рекурсия когда-либо завершит работу.