Параметры и аргументы функции

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

Параметры представляют собой локальные переменные, которым присваиваются значения в момент вызова функции. Конкретные значения, которые передаются в функцию при ее вызове, будем называть аргументами. Следует иметь в виду, что встречается иная терминология. Например, формальные параметры и фактические параметры. В Python же обычно все называют аргументами.

Рассмотрим схему и поясняющий ее пример:

Параметры и аргументы функции. Схема и пример

Когда функция вызывается, то ей передаются аргументы. В примере указаны глобальные переменные num1 и num2. Однако на самом деле передаются не эти переменные, а их значения. В данном случае числа 100 и 12. Другими словами, мы могли бы писать mathem(100, 12). Разницы не было бы.

Когда интерпретатор переходит к функции, чтобы начать ее исполнение, он присваивает переменным-параметрам переданные в функцию значения-аргументы. В примере переменной a будет присвоено 100, b будет присвоено 12.

Изменение значений a и b в теле функции никак не скажется на значениях переменных num1 и num2. Они останутся прежними. В Python такое поведение характерно для неизменяемых типов данных, к которым относятся, например, числа и строки. Говорят, что в функцию данные передаются по значению. Так, когда a присваивалось число 100, то это было уже другое число, не то, на которое ссылается переменная num1. Число 100 было скопировано и помещено в отдельную ячейку памяти для переменной a.

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

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

Произвольное количество аргументов

Обратим внимание еще на один момент. Количество аргументов и параметров совпадает. Нельзя передать три аргумента, если функция принимает только два. Нельзя передать один аргумент, если функция требует два обязательных. В рассмотренном примере они обязательные.

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

def cylinder(h, r = 1):
    side = 2 * 3.14 * r * h
    circle = 3.14 * r**2
    full = side + 2 * circle
    return full
 
figure1 = cylinder(4, 3)
figure2 = cylinder(5)
print(figure1)
print(figure2)

Вывод:

131.88
37.68

При втором вызове cylinder() мы указываем только один аргумент. Он будет присвоен переменной-параметру h. Переменная r будет равна 1.

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

А вот при вызове функции, можно явно указывать, какое значение соответствует какому параметру. В этом случае их порядок не играет роли:

… 
figure3 = cylinder(10, 2)
figure4 = cylinder(r=2, h=10)
print(figure3)
print(figure4)

В данном случае оба вызова – это вызовы с одними и теми же аргументами-значениями. Просто в первом случае сопоставление параметрам-переменным идет в порядке следования. Во-втором случае – по ключам, которыми выступают имена параметров.

В Python определения и вызовы функций имеют и другие нюансы, рассмотрение которых мы пока опустим, так как они требуют более глубоких знаний, чем у нас есть на данный момент. Скажем лишь, что функции может быть определена так, что в нее можно передать хоть ни одного аргумента, хоть множество:

def oneOrMany(*a):
    print(a)
 
oneOrMany(1)
oneOrMany('1',1, 2, 'abc')
oneOrMany()

Результат:

(1,)
('1', 1, 2, 'abc')
()

Опять же, судя по скобкам, здесь возникает упомянутый в прошлом уроке кортеж.

Практическая работа

Напишите программу, в которой определены следующие четыре функции:

  1. Функция getInput() не имеет параметров, запрашивает ввод с клавиатуры и возвращает в основную программу полученную строку.

  2. Функция testInput() имеет один параметр. В теле она проверяет, можно ли переданное ей значение преобразовать к целому числу. Если можно, возвращает логическое True. Если нельзя – False.

  3. Функция strToInt() имеет один параметр. В теле преобразовывает переданное значение к целочисленному типу. Возвращает полученное число.

  4. Функция printInt() имеет один параметр. Она выводит переданное значение на экран и ничего не возвращает.

В основной ветке программы вызовите первую функцию. То, что она вернула, передайте во вторую функцию. Если вторая функция вернула True, то те же данные (из первой функции) передайте в третью функцию, а возвращенное третьей функцией значение – в четвертую.

Примеры решения и дополнительные уроки в android-приложении и pdf-версии курса.

Комментарии

Добрый вечер!
Задача стоит в том, что бы сделать "Глубокое копирование списков". Если у нас есть список в списке, мы должны не только копировать внешний список, но и тот, который внутри. Дабы при изменении праобраза копии, не менялись внутренние списки самой копии. Ну в общем, надеюсь поймете о чем я хотел сказать и в чем я ошибся. Мне кажется проблема с возвращением значения в функцию.
вот:

def copy(a,b):
	a = b.copy()
	i = 1
	for q in b:
		if type(q) == list:
			return copy(a[i], b[i])
	i += 1
	return a

Как-то так.

Ответ на от Гость

В Вашей функции счётчик увеличивается вне цикла (вероятно, Вы ошиблись со сдвигом)
def copy(b):
    a = b.copy()
    i = 0
    for q in b:
        if type(q) == list:
            a[i] = copy(b[i])
        i += 1
    return a
В остальном функция работает. Кроме того, лучшим решением было бы не передавать в функцию первый аргумент, так как он является излишним, ведь Ваша функция использует return

def getInput():
    return input('input value: >>> ')
 
def testInput(inArgs):
    try:
        inArgs=int(inArgs)
        return True
    except:
        return False
 
def strToInt(inArgs):
    return int(inArgs)
 
def printInt(inArgs):
    print('str2int:=',inArgs)
 
uAnswer=getInput()
if testInput(uAnswer):
    printInt(strToInt(uAnswer))

Ответ на от aleba

у меня вопрос, а можно ли было ваше решение реализовать через блок if else? просто я сидел думал как сделать ,почти сделал но не получилось, потом увидел ваш пример. Что-то типа такого:
def getInput():
    getText = input()
    return getText
getInput()
 
def testInput(getText):
    if getText == int(getFunction_1):
        return True
    else:
        return False
 
def strToInt(testint):
    getText = int()
    return get
 
def printInt(get):
    print(str(get))
 
getFunction_1 = getInput()
testInput(getInput)

Ответ на от aleba

Нужно, чтобы подпрограмма вернула несколько значений. Рассчитать значение , с использованием процедуры в которой одновременно находиться минимум(min) и максимум (max) двух чисел, где a и b рациональные числа.

Не понимаю зачем нужна 3 функция. Какой смысл преобразывать целое число в целочисленный тип? Мы же с ним int сделали во 2 функции P. S. Спасибо за ваши уроки

Вот решил с помощью if else, перед этим комментарием делал пост с вопросом можно ли так сделать. Удалось с помощью примера выше, там применялась конструкция try except
def getInput():
    return input()
 
 
def testInput(getText):
    if getText == int(getText):
        return True
    else:
        return False
 
 
def strToInt(getText):
    return int(getText)
 
 
def printInt(getText):
    print(str(getText))
 
getFunction_1 = getInput()
if testInput(getFunction_1):
    printInt(strToInt(getText))

Ответ на от Максим

Строка "if getText == int(getText):" лишена смысла, т.к. в ней вы пытаетесь сравнить разные типы данных - str и int, что всегда будет давать False. Плюс ко всему, при вводе не целочисленного числа, попытка преобразовать его в целое с помощью функции int() окончится ошибкой (исключение ValueError). Здесь, на мой взгляд, без оператора try никак не обойтись.

#----------------------------------------------------------------------
def getInput():
    stroka_1 = input("Введите произвольное значение: ")
    return stroka_1
#----------------------------------------------------------------------
def testInput(a):
    try:
        int(a)
        return True
    except:
        return False
#----------------------------------------------------------------------
def strToInt(a):
    return int(a)
#----------------------------------------------------------------------
def printInt(a):
    print("Введенное вами значение: ", a)
#----------------------------------------------------------------------
 
b = getInput()
if testInput(b) == True:
    c = strToInt(b)
    printInt(c)
else:
    print("Вы ввели не целое число.")