Аргументы в функциях. Передача аргументов в функцию. Изменение аргументов в теле функции
Содержание
- 1. Как осуществляется передача аргументов в функцию? Работа механизма передачи аргумента в функцию
- 2. Примеры передачи неизменяемых объектов в функцию
- 3. Примеры передачи изменяемых объектов в функцию
- 4. Способы избежания изменения объектов-аргументов в вызывающем коде
- 5. Особенности передачи аргументов в функцию. Итоги
- Связанные темы
Поиск на других ресурсах:
1. Как осуществляется передача аргументов в функцию? Работа механизма передачи аргумента в функцию
В функцию могут передаваться аргументы. Аргументы – это изменяемые или неизменяемые объекты. В языке Python имеет значение, к какой категории объектов (изменяемых или неизменяемых) принадлежит аргумент.
Например, к изменяемым объектам относятся списки и словари. К неизменяемым объектам относятся числа, строки, кортежи.
Если в функцию передается неизменяемый объект, то этот объект передается «по значению». Это значит, что изменение этого объекта внутри функции не изменит его в вызывающем коде.
Если в функцию передается изменяемый объект, то этот объект передается по «указателю». Изменение такого объекта внутри функции повлияет на этот объект в вызывающем коде.
⇑
2. Примеры передачи неизменяемых объектов в функцию
2.1. Передача числа в функцию.
В примере, в демонстрационных целях реализована функция Mult2(), которая получает параметром число. В теле функции это число удваивается. Полученный результат выводится.
# Передача числа в функцию # Число - это неизменяемый объект, значит передается "по значению" # Объявить функцию, которая получает некоторое число и умножает его на 2 def Mult2(number): # умножить число на 2 number = number*2 # вивести значение числа всередине функции print("Mult2.number = ", number) # Использовать функцию num = 25 # некоторое число Mult2(num) # вызвать функцию # вывести число num после вызова функции print("num = ", num) # num = 25 - число не изменилось
После запуска программа выдаст следующий результат
Mult2.number = 50 num = 25
Как видно из результата, в функции значение числа num умножается на 2 и составляет 50. Однако, этот результат не передается в вызывающий код, здесь значение num остается равным 25 как до вызова функции. Это подтверждает передачу «по значению» неизменяемого объекта, которым есть число.
⇑
2.2. Передача строки в функцию
Демонстрируется работа функции ReverseStr(), которая реверсирует строку, получаемую параметром.
# Передача строки в функцию # Строка - это неизменяемый объект, поэтому передается "по значению" # Объявить функцию, получающую строку, # реверсирует ее и выводит на экран def ReverseStr(text): # Реверсировать строку txt = '' # цикл перебора строки for c in text: txt = c + txt text = txt # вывести реверсованный текст print('ReveseStr.text = ', text) # Вызов функции ReverseStr() Text = "Hello world!" ReverseStr(Text) print("Text = ", Text)
Результат выполнения программы следующий
ReveseStr.text = !dlrow olleH Text = Hello world!
Как видно из результата, строка в теле функции изменяется (реверсируется). Поскольку в функцию передается копия строки, то в теле функции изменяется только эта копия. Оригинал, который был передан в функцию, при вызове функции не изменяется.
⇑
2.3. Передача кортежа в функцию
# Передача кортежа в функцию # Функция, получающая параметром кортеж def PassTuple(T): # Изменить кортеж T = ([1,2], 'a', 25.88) print('PassTuple.T = ', T) # Создать кортеж TT = ( [2, 3.5], True, 'abcd') # Вызвать функцию и передать ей кортеж TT PassTuple(TT) # Вывести кортеж TT print('TT = ', TT)
Результат выполнения программы
PassTuple.T = ([1, 2], 'a', 25.88) TT = ([2, 3.5], True, 'abcd')
Так же, как и в предыдущих двух примерах, передача кортежа в функцию происходит по значению.
⇑
3. Примеры передачи изменяемых объектов в функцию
3.1. Передача списка в функцию
Демонстрируется функция, которая получает список в качестве параметра. Затем в теле функции этот список изменяется (изменяются первый и второй элементы списка).
# Передача списка в функцию. Список - изменяемый объект # Функция, которая получает параметром список def ChangeList(L): # Изменить список L[0] = 777 # Изменить первый элемент списка L[1] = (2, 3) # Изменить второй элемент списка # Вывести список в теле функции print('ChangeList.L = ', L) # Создать список LL = [ [2, 3.5], True, 'abcd' ] # Вывести список LL для контроля print('LL = ', LL) # Вызвать функцию и передать ей список LL ChangeList(LL) # Вывести список LL после вызова функции print('LL = ', LL)
Результат работы программы
LL = [[2, 3.5], True, 'abcd'] ChangeList.L = [777, (2, 3), 'abcd'] LL = [777, (2, 3), 'abcd']
Как видно из результата, изменение списка в теле функции приводит к изменению этого списка в вызывающем коде. Это означает, что список передается по принципу указателя языка C.
⇑
3.2. Передача словаря в функцию
Демонстрируется функция ChangeDict() которая получает словарь в качестве параметра. В теле функции изменяются отдельные элементы словаря, лежащие на позициях с номерами 0 и 2.
# Передача словаря в функцию. Словарь - изменяемый объект # Функция, получающая параметром словарь def ChangeDict(D): # Изменить словарь D['A'] = 100 # Изменить первый элемент списка D['C'] = 300 # Изменить третий элемент списка # Вывести список в теле функции print('ChangeDict.D = ', D) # Создать словарь DD = { 'A':5, 'B':10, 'C':20 } # Вывести словарь DD для контроля print('DD = ', DD) # Вызвать функцию и передать ей словарь DD ChangeDict(DD) # Вывести список DD после вызова функции print('DD = ', DD)
Результат работы программы
DD = {'A': 5, 'B': 10, 'C': 20} ChangeDict.D = {'A': 100, 'B': 10, 'C': 300} DD = {'A': 100, 'B': 10, 'C': 300}
⇑
4. Способы избежания изменения объектов-аргументов в вызывающем коде
В случаях, когда нужно запретить изменение объекта списка внутри функции, можно использовать способы которые описаны ниже.
Способ 1. При передаче списка в функцию можно конвертировать этот список в кортеж с помощью операции tuple(). После этого изменить список в теле функции не удастся.
Нижеследующий код демонстрирует использование операции tuple() для конвертирования списка в кортеж.
# Передача списка в функцию с конвертированием в кортеж def PassList(L): # Попытка изменить список L[0] = 100 # Ошибка! # Вывести список в теле функции print('PassList.L = ', L) # Создать список LL = [ 1, 3, 8, 10 ] # Вызвать функцию и передать ей список LL, который конвертирован в кортеж PassList(tuple(LL)) # Вывести список L после вызова функции print('LL = ', LL)
Список LL передается в функцию PassList() как кортеж
PassList(tuple(LL))
После этого, изменить элемент списка LL в функции PassList() не удастся. Если запустить программу, то будет сгенерировано исключение с сообщением
TypeError: 'tuple' object does not support item assignment
Способ 2. При передаче списка в функцию можно использовать операцию среза [:], как показано в следующей программе
# Передача списка в функцию с конвертированием в срез def PassList(L): # Попытка изменить список L[0] = 100 # Это изменение не повлияет на вызывающй код # Вывести список в теле функции print('PassList.L = ', L) # Создать список LL = [ 1, 3, 8, 10 ] # Вызвать функцию и передать ей список как срез [:] PassList(LL[:]) # Вывести список L после вызова функции print('LL = ', LL)
В вышеприведенном коде при вызове функции с помощью строки
... PassList(LL[:]) ...
срез LL[:] осуществляет копию списка. Таким образом, изменения списка внутри функции не приведут к изменению списка в вызывающем коде, поскольку эти изменения будут выполняться над копией.
После запуска на выполнение, программа выдаст такой результат
PassList.L = [100, 3, 8, 10] LL = [1, 3, 8, 10]
⇑
5. Особенности передачи аргументов в функцию. Итоги
Для аргументов, которые передаются в функцию, можно выделить следующие особенности:
1. Если из внешнего кода вызывается функция с передачей ей аргумента, то в теле функции этот аргумент (объект) автоматически присваивается соответствующей локальной переменной функции.
Например. Демонстрируется автоматическое присвоение локальной переменной функции значения аргумента.
# Аргументы. # Передача аргумента в функцию # Функция, которая получает аргумент и выводит его на экран def Argument(v): print('Argument.v = ', v) return # Демонстрация неявного присваивания value = 'Hello world!' # некоторый объект # передать объект value в функцию Argument(), # происходит неявное присваивание Argument.v = value Argument(value) # Argument.v = Hello world!
2. Аргументы функции – это ссылки на объекты. При передаче аргумента в функцию передается ссылка на объект. Передаваемые ссылки реализованы как указатели в языке C. Поскольку, при передаче в функцию аргумента, копируется ссылка на объект, то сам объект никогда не копируется. Иными словами, не создается автоматическая копия объекта при передаче его в функцию, осуществляется только копия ссылки.
3. Если в теле функции присвоить значение имени переданного параметра, то это не повлияет на значение внешнего аргумента в вызывающем коде. Это связано с тем, что имена аргументов в вызывающем коде становятся новыми именами в области видимости функции.
Например. В примере, в функции Func() изменяется значение параметра D на 25. В вызывающем коде был передан аргумент с таким самым именем D со значением 30. Однако, после вызова функции из вызывающего кода, значение внешнего аргумента D не изменилось, что и надо было доказать.
# Аргументы. # Передача аргумента в функцию - копия объекта не делается # Функция, которая получает аргумент-список def Func(D): D = 25 # здесь D - новое имя print('Func.D = ', D) D = 30 Func(D) # вызов функции print('D = ', D) # D = 30 - значение объекта в функции не изменилось
4. Если в функцию передается аргумент (объект), который есть изменяемым (список, словарь), то изменение этого аргумента внутри функции приведет к изменению аргумента в вызывающем коде. Это касается только изменения составных элементов объекта (отдельный элемент словаря или списка). Если попробовать изменить объект по его общему имени (с помощью операции присваивания =), то изменений в вызывающем коде не будет (передается ссылка на объект, а именно ссылку изменить нельзя).
Например. В нижеследующем примере объявляются две функции, которые делают попытку изменить входной параметр-список по его имени:
- функция ChangeList() – пробует изменить список по имени ссылки L. Это изменение не влияет на внешний список LL, переданный из вызывающего кода. Это связано с тем, что делается копия ссылки, изменения копии не изменяют оригинал;
- функция ChangeList2() – пробует изменить элемент списка по имени ссылки L и позицией элемента. Результат – изменение влияет на внешний список LL в вызывающем коде. Это связано с тем, что копия и оригинал указывают на одни и те же данные (один и тот же участок памяти);
# Аргументы. # Передача изменяемого объекта в качестве аргумента # Функция, которая получает параметр-список и изменяет весь список def ChangeList(L): # Изменить список всередине функции по имени L = [ 1, 2, 3] # не влияет на внешний код # Вывести измененный список print('ChangeList.L = ', L) # ChangeList.L = [1, 2, 3] # Функция, которая получает параметр-список и изменяет элемент списка def ChangeList2(L): # Изменить составной элемент списка L[1] = 'abcd' # влияет на внешний код print('ChangeList2.L = ', L) # ----- Вызывающий код модуля ------- LL = [ 'a', 'b', 'c' ] # некоторый список # 1. Передача списка в функцию ChangeList() и его вывод ChangeList(LL) # передать список в функцию print('LL = ', LL) # LL = ['а', 'b', 'с'] - список не изменился # 2. Передать список LL в функцию ChangeList2() ChangeList2(LL) print('LL = ', LL) # LL = ['a', 'abcd', 'c' ] - список изменился
После выполнения программа выдаст следующий результат
ChangeList.L = [1, 2, 3] LL = ['a', 'b', 'c'] ChangeList2.L = ['a', 'abcd', 'c'] LL = ['a', 'abcd', 'c']
⇑
Связанные темы
- Режимы сопоставления аргументов. Классификация. Сопоставление по позиции. Сопоставление по именам. Аргументы по умолчанию
- Режимы сопоставления аргументов. Аргументы переменной длины. Комбинирование разных способов сопоставления аргументов. Примеры
⇑