Как передать список в функцию python
Перейти к содержимому

Как передать список в функцию python

  • автор:

Как передать функцию как параметр в Python?

Поскольку функция в Python является объектом, ее можно передавать в другую функцию в качестве аргумента. При этом функция в аргументе указывается без круглых скобок, то есть передается только ссылка на функцию.

def calculate(a, b, operation): result = operation(a, b) return result def sum(a, b): return a + b def multiply(a, b) return a * b calculate(2, 3, sum) # 5 calculate(3, 4, multiply) # 12 

Функции, которые могут принимать другие функции в качестве аргументов, также называются функциями высшего порядка. Яркий пример функции высшего порядка — функция map() , которая принимает аргументом функцию и итерируемую последовательность, и применяет функцию-параметр к каждому элементу последовательности.

Python. Аргументы в функциях. Передача аргументов в функцию. Изменение аргументов в теле функции

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

Например, к изменяемым объектам относятся списки и словари. К неизменяемым объектам относятся числа, строки, кортежи.

Если в функцию передается неизменяемый объект, то этот объект передается «по значению». Это значит, что изменение этого объекта внутри функции не изменит его в вызывающем коде.

Если в функцию передается изменяемый объект, то этот объект передается по «указателю». Изменение такого объекта внутри функции повлияет на этот объект в вызывающем коде.

2. Примеры передачи неизменяемых объектов в функцию
2.1. Передача числа в функцию.

В примере, в демонстрационных целях реализована функция Mult2() , которая получает параметром число. В теле функции это число удваивается. Полученный результат выводится.

# Передача числа в функцию # Число - это неизменяемый объект, значит передается "по значению" # Объявить функцию, которая получает некоторое число и умножает его на 2 def Mult2(number): # умножить число на 2 number = number*2 # вивести значение числа всередине функции print("Mult2.number color: #ff0000;"># Использовать функцию num = 25 # некоторое число Mult2(num) # вызвать функцию # вывести число num после вызова функции print("num color: #ff0000;"># 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 color: #333300;">⇑ 
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 = ChangeDict.D = DD =

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']

Связанные темы

  • Режимы сопоставления аргументов. Классификация. Сопоставление по позиции. Сопоставление по именам. Аргументы по умолчанию
  • Режимы сопоставления аргументов. Аргументы переменной длины. Комбинирование разных способов сопоставления аргументов. Примеры

Распаковка аргументов для передачи в функцию Python

Бывают ситуации, когда для функции, требующей отдельных позиционных аргументов, значения этих аргументов уже находятся в списке или кортеже, и для вызова функции должны быть распакованы.

Например, встроенная range() функция ожидает отдельные аргументы start и stop . Если они не доступны отдельно, то можно распаковать аргументы из списка list или кортежа tuple , вызвав функцию с переменной этого списка/кортежа, а впереди нее поставить символ одной звездочки * :

# обычный вызов с отдельными аргументами >>> list(range(3, 6)) # [3, 4, 5] >>> args = [3, 6] # вызов с аргументами, распакованными из списка >>> list(range(*args)) # [3, 4, 5] 

Таким же образом, из словаря dict в функцию можно передать ключевые аргументы, только в этом случае, перед переменной словаря ставится два символов звездочки ** :

>>> def parrot(voltage, state='a stiff', action='voom'): . print("-- This parrot wouldn't", action, end=' ') . print("if you put", voltage, "volts through it.", end=' ') . print("E's", state, "!") . >>> d = "voltage": "four million", "state": "bleedin' demised", "action": "VOOM"> >>> parrot(**d) # -- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demis 
  • символом * - распаковывают последовательности в качестве элементов которых одно значение (списки, кортежи, множества)
  • два символа ** - распаковывают последовательности в качестве элементов которых имеется ключ и значение (словари)

Примеры распаковки списков и словарей с аргументами для функции:

date_inf = 'year': "2020", 'month': "12", 'day': "06"> f_name = " - - .txt".format(**date_inf) print(f_name) # 2020-12-06.txt fruits = ['lemon', 'orange', 'banana', 'tomato'] print(*fruits) # lemon orange banana tomato 

Распаковку аргументов можно использовать несколько раз в функции:

date_info = 'year': "2020", 'month': "01", 'day': "01"> track_info = 'artist': "Beethoven", 'title': 'Symphony No 5'> filename = " - - - - .txt".format(**date_info, **track_info) print(filename) # 2020-01-01-Beethoven-Symphony No 5.txt 
fruits = ['lemon', 'orange', 'banana', 'tomato'] first, second, *orher = fruits print(orher) # ['banana', 'tomato'] first, *orher = fruits print(orher) # ['orange', 'banana', 'tomato'] first, *middle, last = fruits print(middle) # ['orange', 'banana'] 
  • КРАТКИЙ ОБЗОР МАТЕРИАЛА.
  • Функции это объекты
  • Функции могут иметь атрибуты
  • Функции могут храниться в структурах данных
  • Функции могут быть вложенными
  • Передача функции в качестве аргумента другой функции
  • Область видимости переменных функции
  • Операторы global и nonlocal
  • Параметры (аргументы) функции
  • Ключевые аргументы в определении функции Python
  • Значение аргумента по умолчанию в функциях Python
  • Варианты передачи аргументов в функцию Python
  • Переменные аргументов *args и **kwargs в функции Python
  • Распаковка аргументов для передачи в функцию Python
  • Как оцениваются аргументы при вызове функции?
  • Строгие правила передачи аргументов в функцию Python
  • Инструкция return
  • Анонимные функции (lambda-выражения)
  • Строки документации в функциях Python
  • Рекурсия
  • Замыкания в функциях Python
  • Перегрузка функций

Список Python как аргумент по умолчанию

В разделе рассмотрен один из самых опасных случаев использование списка list (изменяемых последовательностей), когда список используется, как аргумент по умолчанию для функций.

Сморим следующий пример.

# определим функцию, где корзина покупателя 'basket' # по умолчанию должна быть пустым списком покупок def add_fruit(fruit, basket=[]): # при покупке - корзина пополняется basket.append(fruit) return basket >>> b = add_fruit("banana") >>> b # ['banana'] # Внимание! Аргумент `basket` не передается. >>> c = add_fruit("apple") >>> c # ['banana', 'apple'] # Да ладно, ведь при инициализации # в аргументах функции список пустой. 

Из примера видно, что функция add_fruit() вызывается дважды, при чем аргумент basket (список сделанных покупок) не передается! Конечным результатом является список из двух товаров ['banana', 'apple'] , как это произошло?

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

Другими словами, пустой список создается один раз и аргумент basket указывает на него в течение всего времени существования функции. Единственное исключение - это когда аргументу basket передается другой список, но это не изменит значение по умолчанию. Всякий раз, когда вызывается функция снова, без указания basket , то она будет использовать значение по умолчанию, которое было создано при определении функции.

Чтобы избежать подобного поведения, аргументы по умолчанию должны быть неизменяемыми! В данном конкретном случае, можно аргументу basket присвоить значение None и создать пустой список, если basket is None , в противном случае работать со списком, который передается в функцию.

def add_fruit(fruit, basket=None): if basket is None: basket = [] basket.append(fruit) return basket >>> b = add_fruit("banana") >>> b # ['banana'] >>> c = add_fruit("apple") >>> c # ['apple'] 

Теперь создается пустой список покупок всякий раз, когда аргумент basket не передается функции, что исправляет ошибку.

  • КРАТКИЙ ОБЗОР МАТЕРИАЛА.
  • Список Python как аргумент по умолчанию
  • Использование списка в качестве стека
  • Использование списка в качестве очереди
  • Генератор списка list
  • Эффективное использование генераторов списков
  • Операция присваивания на месте и списки
  • Поведение списков Python в разных областях видимости
  • Сравнение и идентичность двух списков
  • Как получить несколько последних элементов списка

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *