Python. Аргументи в функціях. Передача аргументів у функцію. Зміна аргументів у тілі функції

Аргументи в функціях. Передача аргументів у функцію. Зміна аргументів у тілі функції


Зміст


Пошук на інших ресурсах:




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 = ['a', 'b', 'c'] - список не змінився

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

 


Зв’язані теми