Введение в Python. Часть 8. Функции
Функция в Python — это объект, принимающий аргументы и возвращающий значение. Со встроенными функциями вы уже сталкивались в предыдущих уроках. Например, когда когда мы хотели узнать сумму всех чисел в списке. Можете заглянуть в выпуск про списки.
Видео: Глеб Лиманский
Тогда мы использовали встроенную функцию sum(). На вход мы передавали аргумент — список с числами, а функция возвращала нам результат — сумму этих чисел.
Если бы такой функции в Python не существовало, то мы бы могли написать что-то вроде такого кода:
И это сразу несколько строчек кода, хоть и очень простого. А с функцией мы можем заменить их на всего лишь на одно слово, что гораздо удобнее. К тому же функция устроена более универсальным образом. Какой-бы список мы ей не передали, она все равно вернет нам сумму его элементов. Не важно как будут называться этот список и будет ли у него вообще название. Главное, чтобы в списке были числа!
Подписывайтесь на рассылку «Мастерской»
Вы узнаете о крутых инструментах для сбора, анализа и визуализации данных
А в нашем коде, где мы сами считаем сумму, речь идет о конкретном списке, который называется my_list. То есть без замены названия этот код нельзя будет использовать для другого списка. Поэтому, если бы функции суммы не существовало в питоне, то нам было бы удобнее написать ее самим. Давайте оформим наш кусочек кода в функцию.
Чтобы определить функцию используется конструкция def. Дальше пишем имя функции, скобки и двоеточие. После двоеточия вы кодом прописываете, что именно должна делать функция, а дальше с помощью return функция возвращает результат. А чтобы использовать функцию нужно написать ее название и в скобка и передать ей аргумент.
Вот так почти всегда будет выглядеть функция.
Но она не всегда должна что-то принимать на вход или что-то возвращать. Вот пример функции, которая просто здоровается — распечатывает «Hi!», но не принимает аргументов и ничего не возвращает. И если напишете print(say_hi()), то в ответе вы увидите None.
Функция может ничего не принимать на вход, но что-то все же возвращать, а не просто распечатывать. Вот, например, функция, которая спрашивает у пользователя имя и возвращает его.
При этом функция может принимать и возвращать практически любые объекты и данные. Вот функция, которая принимает на вход имя человека и здоровается с ним. Но мы можем передать ей не просто имя не в виде строчки с ним, а нашу функцию get_name(). Она спросит у пользователя имя, и передаст его функции, которая с ним поздоровается.
Также для функций существует отдельный вид аргументов. Один из них — необязательный аргумент. Например, мы хотим усовершенствовать нашу функцию say_hi_to(). Теперь она должна не просто здороваться с пользователем, но и заводить с ним небольшую беседу. Поэтому добавим в функцию необязательный аргумент small_talk.
По умолчанию мы назначили small_talk = «Как дела?». Когда мы будем вызывать функцию, нам не нужно указывать этот аргумент, он уже есть по умолчанию. Нам нужно лишь передать имя, дальше функция сама спросит пользователя «Как дела?».
Отдельно указывать аргумент small_talk при вывозе функции нужно только тогда, когда мы хотим внести в него какие-то изменения. Например, мы хотим, чтобы вместо «Как дела?» функция спросила что-то другое.
Давайте посмотрим, как функции могут использоваться на практике. Напишем функцию, которая будет очищать телефонный номер от пробелов, дефисов и скобок. Допустим у нас есть датасет, где содержатся данные о владельцах телефонных номеров. И нам нужно бы привести все телефоны к одному формату. Сначала мы будем писать функцию, а потом использовать ее для датасета.
Допустим, наши данные у нас хранятся в виде подобного словаря — phone_book = {‘Alice’: ‘8-987-657 12 11’, ‘Bob’:’89012345678′, ‘Jack’:’8 (9 1 2) 3 4 5 6 7 8 9′}. Ключами тут являются имена, а значениями — телефоны, которые написаны по-разному: с пробелами, дефисами, скобками. Нам нужно к каждому из этих номеров приметь функцию clean_tel().
Давайте теперь напишем функцию, которая именно это и будет делать. На вход ей нужно будет передать словарь с «грязными» номерами, а вернет она список с чистыми данными.
Такой список можно будет легко сохранить в табличку.
Анонимная функция
В Python есть анонимные функции — лямбды. Они подчиняющиеся более строгому, но более лаконичному синтаксису, чем обычные функции Python. И работаю быстрее. Анонимные функции могут содержать лишь одно выражение. Они создаются с помощью инструкции lambda. Кроме этого, их не обязательно присваивать переменной.
Чтобы было проще, давайте сначала напишем уже известную обычную функцию, а потом перепишем ее с помощью lambda. Вот пример функции, которая просто складывает два числа.
А вот как она выглядит, если переписать ее с помощью lambda.
После инструкции lambda нужно указать аргументы, а через двоеточие, что функция должна сделать с этими аргументами.
Лямбда-функцию не обязательно как-то называть. Ее можно вызвать и без имени. Нужно поместить функцию в скобки. И рядом же в скобках указать аргументы.
Кстати, и нашу функцию say_hi() тоже можно переписать с помощью lambda.
Это все основные принципы работы функций в Python. Если вы хотите прочитать о дополнительных возможностях функций, можете сделать это здесь. И, как всегда, тетрадка Jupyter Notebook с этого урока лежит на нашем GitHub.
синтаксис, логика и применение ~ PythonRu
Введение
Определение
Вот пример простой функции:
def compute_surface(radius):
from math import pi
return pi * radius * radius
Для определения функции нужно всего лишь написать ключевое слово def
перед ее именем, а после — поставить двоеточие. Следом идет блок инструкций.
Последняя строка в блоке инструкций может начинаться с return
, если нужно вернуть какое-то значение. Если инструкции return
нет, тогда по умолчанию функция будет возвращать объект None
. Как в этом примере:
i = 0
def increment():
global i
i += 1
Функция инкрементирует глобальную переменную i
и возвращает None
(по умолчанию).
Вызовы
Для вызова функции, которая возвращает переменную, нужно ввести:
surface = compute_surface(1.)
Для вызова функции, которая ничего не возвращает:
increment()
Еще
Функцию можно записать в одну строку, если блок инструкций представляет собой простое выражение:
def sum(a, b): return a + b
Функции могут быть вложенными:
def func1(a, b):
def inner_func(x):
return x*x*x
return inner_func(a) + inner_func(b)
Функции — это объекты, поэтому их можно присваивать переменным.
Инструкция return
Возврат простого значения
Аргументы можно использовать для изменения ввода и таким образом получать вывод функции. Но куда удобнее использовать инструкцию return
, примеры которой уже встречались ранее. Если ее не написать, функция вернет значение
.
Возврат нескольких значений
Пока что функция возвращала только одно значение или не возвращала ничего (объект None). А как насчет нескольких значений? Этого можно добиться с помощью массива. Технически, это все еще один объект. Например:
def stats(data):
"""данные должны быть списком"""
_sum = sum(data)
mean = _sum / float(len(data))
variance = sum([(x-mean)**2/len(data) for x in data])
return mean,variance
m, v = stats([1, 2, 1])
Аргументы и параметры
В функции можно использовать неограниченное количество параметров, но число аргументов должно точно соответствовать параметрам. Эти параметры представляют собой позиционные аргументы. Также Python предоставляет возможность определять значения по умолчанию, которые можно задавать с помощью аргументов-ключевых слов.
Параметр — это имя в списке параметров в первой строке определения функции. Он получает свое значение при вызове. Аргумент — это реальное значение или ссылка на него, переданное функции при вызове. В этой функции:
def sum(x, y):
return x + y
x и y — это параметры, а в этой:
sum(1, 2)
1 и 2 — аргументы.
При определении функции параметры со значениями по умолчанию нужно указывать до позиционных аргументов:
def compute_surface(radius, pi=3.14159):
return pi * radius * radius
Если использовать необязательный параметр, тогда все, что указаны справа, должны быть параметрами по умолчанию.
Выходит, что в следующем примере допущена ошибка:
def compute_surface(radius=1, pi):
return pi * radius * radius
Для вызовов это работает похожим образом. Сначала нужно указывать все позиционные аргументы, а только потом необязательные:
S = compute_surface(10, pi=3.14)
На самом деле, следующий вызов корректен (можно конкретно указывать имя позиционного аргумента), но этот способ не пользуется популярностью:
S = compute_surface(radius=10, pi=3.14)
А этот вызов некорректен:
S = compute_surface(pi=3.14, 10)
При вызове функции с аргументами по умолчанию можно указать один или несколько, и порядок не будет иметь значения:
def compute_surface2(radius=1, pi=3.14159):
return pi * radius * radius
S = compute_surface2(radius=1, pi=3.14)
S = compute_surface2(pi=3.14, radius=10.)
S = compute_surface2(radius=10.)
Можно не указывать ключевые слова, но тогда порядок имеет значение. Он должен соответствовать порядку параметров в определении:
S = compute_surface2(10., 3.14)
S = compute_surface2(10.)
Если ключевые слова не используются, тогда нужно указывать все аргументы:
def f(a=1,b=2, c=3):
return a + b + c
Второй аргумент можно пропустить:
f(1,,3)
Чтобы обойти эту проблему, можно использовать словарь:
params = {'a':10, 'b':20}
S = f(**params)
Значение по умолчанию оценивается и сохраняется только один раз при определении функции (не при вызове). Следовательно, если значение по умолчанию — это изменяемый объект, например, список или словарь, он будет меняться каждый раз при вызове функции. Чтобы избежать такого поведения, инициализацию нужно проводить внутри функции или использовать неизменяемый объект:
def inplace(x, mutable=[]):
mutable.append(x)
return mutable
res = inplace(1)
res = inplace(2)
print(inplace(3))
[1, 2, 3]
def inplace(x, lst=None):
if lst is None: lst=[]
lst.append()
return lst
Еще один пример изменяемого объекта, значение которого поменялось при вызове:
def change_list(seq):
seq[0] = 100
original = [0, 1, 2]
change_list(original)
original
[100, 1, 2]
Дабы не допустить изменения оригинальной последовательности, нужно передать копию изменяемого объекта:
original = [0, 1, 2]
change_list(original[:])
original
[0, 1, 2]
Указание произвольного количества аргументов
Позиционные аргументы
Иногда количество позиционных аргументов может быть переменным. Примерами таких функций могут быть max()
и min()
. Синтаксис для определения таких функций следующий:
def func(pos_params, *args):
block statememt
При вызове функции нужно вводить команду следующим образом:
func(pos_params, arg1, arg2, ...)
Python обрабатывает позиционные аргументы следующим образом: подставляет обычные позиционные аргументы слева направо, а затем помещает остальные позиционные аргументы в кортеж (*args), который можно использовать в функции.
Вот так:
def add_mean(x, *data):
return x + sum(data)/float(len(data))
add_mean(10,0,1,2,-1,0,-1,1,2)
10.5
Если лишние аргументы не указаны, значением по умолчанию будет пустой кортеж.
Произвольное количество аргументов-ключевых слов
Как и в случае с позиционными аргументами можно определять произвольное количество аргументов-ключевых слов следующим образом (в сочетании с произвольным числом необязательных аргументов из прошлого раздела):
def func(pos_params, *args, **kwargs):
block statememt
При вызове функции нужно писать так:
func(pos_params, kw1=arg1, kw2=arg2, ...)
Python обрабатывает аргументы-ключевые слова следующим образом: подставляет обычные позиционные аргументы слева направо, а затем помещает другие позиционные аргументы в кортеж (*args), который можно использовать в функции (см. предыдущий раздел). В конце концов, он добавляет все лишние аргументы в словарь (**kwargs), который сможет использовать функция.
Есть функция:
def print_mean_sequences(**kwargs): def mean(data): return sum(data)/float(len(data)) for k, v in kwargs.items(): print k, mean(v) print_mean_sequences(x=[1,2,3], y=[3,3,0])
y 2.0
x 2.0
Важно, что пользователь также может использовать словарь, но перед ним нужно ставить две звездочки (**):
print_mean_sequences(**{'x':[1,2,3], 'y':[3,3,0]})
y 2.0
x 2.0
Порядок вывода также не определен, потому что словарь не отсортирован.
Документирование функции
Определим функцию:
def sum(s,y): return x + y
Если изучить ее, обнаружатся два скрытых метода (которые начинаются с двух знаков нижнего подчеркивания), среди которых есть
. Он нужен для настройки документации функции. Документация в Python называется docstring
и может быть объединена с функцией следующим образом:
def sum(x, y):
"""Первая срока - заголовок
Затем следует необязательная пустая строка и текст
документации.
"""
return x+y
Команда docstring
должна быть первой инструкцией после объявления функции. Ее потом можно будет извлекать или дополнять:
print(sum.__doc__)
sum.__doc__ += "some additional text"
Методы, функции и атрибуты, связанные с объектами функции
Если поискать доступные для функции атрибуты, то в списке окажутся следующие методы (в Python все является объектом — даже функция):
sum.func_closure sum.func_defaults sum.func_doc sum.func_name
sum.func_code sum.func_dict sum.func_globals
И несколько скрытых методов, функций и атрибутов. Например, можно получить имя функции или модуля, в котором она определена:
>>> sum.__name__
"sum"
>>> sum.__module
"__main__"
Есть и другие. Вот те, которые не обсуждались:
sum.__call__ sum.__delattr__ sum.__getattribute__ sum.__setattr__
sum.__class__ sum.__dict__ sum.__globals__ sum.__new__ sum.__sizeof__
sum.__closure__ sum.__hash__ sum.__reduce__ sum.__str__
sum.__code__ sum.__format__ sum.__init__ sum.__reduce_ex__ sum.__subclasshook__
sum.__defaults__ sum.__get__ sum.__repr__
Рекурсивные функции
Рекурсия — это не особенность Python. Это общепринятая и часто используемая техника в Computer Science, когда функция вызывает сама себя. Самый известный пример — вычисление факториала n! = n * n — 1 * n -2 * … 2 *1. Зная, что 0! = 1, факториал можно записать следующим образом:
def factorial(n):
if n != 0:
return n * factorial(n-1)
else:
return 1
Другой распространенный пример — определение последовательности Фибоначчи:
f(0) = 1
f(1) = 1
f(n) = f(n-1) + f(n-2)
Рекурсивную функцию можно записать так:
def fibbonacci(n):
if n >= 2:
else:
return 1
Важно, чтобы в ней было была конечная инструкция, иначе она никогда не закончится. Реализация вычисления факториала выше, например, не является надежной. Если указать отрицательное значение, функция будет вызывать себя бесконечно. Нужно написать так:
def factorial(n):
assert n > 0
if n != 0:
return n * factorial(n-1)
else:
return 1
Важно!
Рекурсия позволяет писать простые и элегантные функции, но это не гарантирует эффективность и высокую скорость исполнения.
Если рекурсия содержит баги (например, длится бесконечно), функции может не хватить памяти. Задать максимальное значение рекурсий можно с помощью модуля sys
.
Глобальная переменная
Вот уже знакомый пример с глобальной переменной:
i = 0
def increment():
global i
i += 1
Здесь функция увеличивает на 1 значение глобальной переменной i
. Это способ изменять глобальную переменную, определенную вне функции. Без него функция не будет знать, что такое переменная i
. Ключевое слово global
можно вводить в любом месте, но переменную разрешается использовать только после ее объявления.
За редкими исключениями глобальные переменные лучше вообще не использовать.
Присвоение функции переменной
С существующей функцией func
синтаксис максимально простой:
variable = func
Переменным также можно присваивать встроенные функции. Таким образом позже есть возможность вызывать функцию другим именем. Такой подход называется непрямым вызовом функции.
Менять название переменной также разрешается:
def func(x): return x
a1 = func
a1(10)
10
a2 = a1
a2()
10
В этом примере a1, a2 и func
имеют один и тот же id. Они ссылаются на один объект.
Практический пример — рефакторинг существующего кода. Например, есть функция sq
, которая вычисляет квадрат значения:
def sq(x): return x*x
Позже ее можно переименовать, используя более осмысленное имя. Первый вариант — просто сменить имя. Проблема в том, что если в другом месте кода используется sq
, то этот участок не будет работать. Лучше просто добавить следующее выражение:
square = sq
Последний пример. Предположим, встроенная функция была переназначена:
dir = 3
Теперь к ней нельзя получить доступ, а это может стать проблемой. Чтобы вернуть ее обратно, нужно просто удалить переменную:
del dir
dir()
Анонимная функция: лямбда
Лямбда-функция — это короткая однострочная функция, которой даже не нужно имя давать. Такие выражения содержат лишь одну инструкцию, поэтому, например, if
, for
и while
использовать нельзя. Их также можно присваивать переменным:
product = lambda x,y: x*y
В отличие от функций, здесь не используется ключевое слово return
. Результат работы и так возвращается.
С помощью type()
можно проверить тип:
>>> type(product)
function
На практике эти функции редко используются. Это всего лишь элегантный способ записи, когда она содержит одну инструкцию.
power = lambda x=1, y=2: x**y
square = power
square(5.)
25
power = lambda x,y,pow=2: x**pow + y
[power(x,2, 3) for x in [0,1,2]]
[2, 3, 10]
Изменяемые аргументы по умолчанию
>>> def foo(x=[]):
... x.append(1)
... print x
...
>>> foo()
[1]
>>> foo()
[1, 1]
>>> foo()
[1, 1, 1]
Вместо этого нужно использовать значение «не указано» и заменить на изменяемый объект по умолчанию:
>>> def foo(x=None):
... if x is None:
... x = []
... x.append(1)
... print x
>>> foo()
[1]
>>> foo()
[1]
Использование функций в Python—ArcGIS Pro
Функция – это часть приложения, выполняющая определенную задачу. Функция может включаться в более крупную программу.
В ArcPy все функции геообработки представлены в виде функций, однако не все функции являются инструментами геообработки. Кроме инструментов в ArcPy имеется несколько функций для улучшения рабочих процессов геообработки с использованием Python. Функции могут использоваться для создания списков определенных наборов данных, извлечения свойств набора данных, проверки имени таблицы перед ее добавлением в базу геоданных, а также выполнения многих других полезных задач геообработки. Эти функции имеются только в ArcPy, они отсутствуют в числе инструментов ArcGIS, поскольку предназначены для алгоритмов Python.
В общем вид функции аналогичен виду инструмента, она принимает аргументы и возвращает какое-то значение. Значение, возвращаемое неинструментальными функциями, может быть различным – это может быть все что угодно, от строк до объектов геообработки. Инструментальные функции всегда возвращают объект Result и предоставляют поддержку сообщений геообработки.
В следующем примере используются две функции ArcPy: GetParameterAsText для получения входного аргумента и Exists для определения, существует ли вход. Функция Exists возвращает логический аргумент (Истина (True) или Ложь (False)).
import arcpy
input = arcpy.GetParameterAsText(0)
if arcpy.Exists(input):
print("Data exists")
else:
print("Data does not exist")
В следующем примере кода с помощью функции ListFeatureClasses создается список Python классов пространственных объектов, после этого производится циклический обход списка и вырезание каждого отдельного класса пространственных объектов с помощью класса объектов границ.
import arcpy
import os
# The workspace environment needs to be set before ListFeatureClasses
# to identify which workspace the list will be based on
#
arcpy.env.workspace = "c:/data"
out_workspace = "c:/data/results/"
clip_features = "c:/data/testarea/boundary.shp"
# Loop through a list of feature classes in the workspace
#
for fc in arcpy.ListFeatureClasses():
# Set the output name to be the same as the input name, and
# locate in the 'out_workspace' workspace
#
output = os.path.join(out_workspace, fc)
# Clip each input feature class in the list
#
arcpy.Clip_analysis(fc, clip_features, output, 0.1)
Связанные разделы
Отзыв по этому разделу?
Интерактивный учебник языка Python
1. Функции
Напомним, что в математике факториал числа n определяется как n! = 1 ⋅ 2 ⋅ … ⋅ n. Например, 5! = 1 ⋅ 2 ⋅ 3 ⋅ 4 ⋅ 5 = 120. Ясно, что факториал можно легко посчитать, воспользовавшись циклом for. Представим, что нам нужно в нашей программе вычислять факториал разных чисел несколько раз (или в разных местах кода). Конечно, можно написать вычисление факториала один раз, а затем используя Copy-Paste вставить его везде, где это будет нужно.
# вычислим 3! res = 1 for i in range(1, 4): res *= i print(res) # вычислим 5! res = 1 for i in range(1, 6): res *= i print(res)
Однако, если мы ошибёмся один раз в начальном коде, то потом эта ошибка попадёт в код во все места, куда мы скопировали вычисление факториала. Да и вообще, код занимает больше места, чем мог бы. Чтобы избежать повторного написания одной и той же логики, в языках программирования существуют функции.
Функции — это такие участки кода, которые изолированы от остальный программы и выполняются только тогда, когда вызываются. Вы уже встречались с функциями sqrt(), len() и print(). Они все обладают общим свойством: они могут принимать параметры (ноль, один или несколько), и они могут возвращать значение (хотя могут и не возвращать). Например, функция sqrt() принимает один параметр и возвращает значение (корень числа). Функция print() принимает переменное число параметров и ничего не возвращает.
Покажем, как написать функцию factorial(), которая принимает один параметр — число, и возвращает значение — факториал этого числа.
def factorial(n): res = 1 for i in range(1, n + 1): res *= i return res print(factorial(3)) print(factorial(5))
Дадим несколько объяснений. Во-первых, код функции должен размещаться в начале программы, вернее, до того места, где мы захотим воспользоваться функцией factorial(). Первая строчка этого примера является описанием нашей функции. factorial — идентификатор, то есть имя нашей функции. После идентификатора в круглых скобках идет список параметров, которые получает наша функция. Список состоит из перечисленных через запятую идентификаторов параметров. В нашем случае список состоит из одной величины n. В конце строки ставится двоеточие.
Далее идет тело функции, оформленное в виде блока, то есть с отступом. Внутри функции вычисляется значение факториала числа n и оно сохраняется в переменной res. Функция завершается инструкцией return res, которая завершает работу функции и возвращает значение переменной res.
Инструкция return может встречаться в произвольном месте функции, ее исполнение завершает работу функции и возвращает указанное значение в место вызова. Если функция не возвращает значения, то инструкция return используется без возвращаемого значения. В функциях, которым не нужно возвращать значения, инструкция return может отсутствовать.
Приведём ещё один пример. Напишем функцию max(), которая принимает два числа и возвращает максимальное из них (на самом деле, такая функция уже встроена в Питон).
10 20
def max(a, b): if a > b: return a else: return b print(max(3, 5)) print(max(5, 3)) print(max(int(input()), int(input())))
Теперь можно написать функцию max3(), которая принимает три числа и возвращает максимальное их них.
def max(a, b): if a > b: return a else: return b def max3(a, b, c): return max(max(a, b), c) print(max3(3, 5, 4))Встроенная функция max() в Питоне может принимать переменное число аргументов и возвращать максимум из них. Приведём пример того, как такая функция может быть написана.
def max(*a): res = a[0] for val in a[1:]: if val > res: res = val return res print(max(3, 5, 4))Все переданные в эту функцию параметры соберутся в один кортеж с именем a, на что указывает звёздочка в строке объявления функции.
2. Локальные и глобальные переменные
Внутри функции можно использовать переменные, объявленные вне этой функции
def f(): print(a) a = 1 f()
Здесь переменной a
присваивается значение 1, и функция f()
печатает это значение, несмотря на то, что до объявления функции f
эта переменная
не инициализируется. В момент вызова функции f()
переменной a
уже присвоено значение, поэтому функция f()
может вывести его на экран.
Такие переменные (объявленные вне функции, но доступные внутри функции) называются глобальными.
Но если инициализировать какую-то переменную внутри функции, использовать эту переменную вне функции не удастся. Например:
def f(): a = 1 f() print(a)
Получим ошибку NameError: name 'a' is not defined
. Такие переменные, объявленные внутри функции,
называются локальными. Эти переменные становятся недоступными после выхода из функции.
Интересным получится результат, если попробовать изменить значение глобальной переменной внутри функции:
def f(): a = 1 print(a) a = 0 f() print(a)
Будут выведены числа 1 и 0. Несмотря на то, что значение переменной a
изменилось внутри функции, вне функции оно осталось прежним! Это сделано в целях
“защиты” глобальных переменных от случайного изменения из функции.
Например, если функция будет вызвана из цикла по переменной i
, а в этой функции
будет использована переменная i
также для организации цикла, то эти переменные должны
быть различными. Если вы не поняли последнее предложение, то посмотрите на следующий код и подумайте, как бы он работал,
если бы внутри функции изменялась переменная i.
def factorial(n): res = 1 for i in range(1, n + 1): res *= i return res for i in range(1, 6): print(i, '! = ', factorial(i), sep='')Если бы глобальная переменная i изменялась внутри функции, то мы бы получили вот что:
5! = 1 5! = 2 5! = 6 5! = 24 5! = 120Итак, если внутри функции модифицируется значение некоторой переменной, то переменная с таким именем становится локальной переменной, и ее модификация не приведет к изменению глобальной переменной с таким же именем.
Более формально: интерпретатор Питон считает переменную локальной для данной функции, если в её коде
есть хотя бы одна инструкция, модифицирующая значение переменной, то эта переменная считается локальной
и не может быть использована до инициализации. Инструкция, модифицирующая значение переменной — это операторы =
, +=
, а также использование переменной в качестве параметра цикла for
.
При этом даже если инструкция,
модицифицирующая переменную никогда не будет выполнена, интерпретатор это проверить
не может, и переменная все равно считается локальной. Пример:
def f(): print(a) if False: a = 0 a = 1 f()
Возникает ошибка: UnboundLocalError: local variable 'a' referenced before assignment
.
А именно, в функции f()
идентификатор a
становится локальной переменной,
т.к. в функции есть команда, модифицирующая переменную a
, пусть даже никогда и
не выполняющийся (но интерпретатор не может это отследить). Поэтому вывод переменной a
приводит к обращению к неинициализированной локальной переменной.
Чтобы функция могла изменить значение глобальной переменной, необходимо объявить эту переменную
внутри функции, как глобальную, при помощи ключевого слова global
:
def f(): global a a = 1 print(a) a = 0 f() print(a)
В этом примере на экран будет выведено 1 1, так как переменная a
объявлена, как глобальная,
и ее изменение внутри функции приводит к тому, что и вне функции переменная
будет доступна.
Тем не менее, лучше не изменять значения глобальных переменных внутри функции. Если ваша функция должна поменять какую-то переменную, пусть лучше она вернёт это значением, и вы сами при вызове функции явно присвоите в переменную это значение. Если следовать этим правилам, то функции получаются независимыми от кода, и их можно легко копировать из одной программы в другую.
Например, пусть ваша программа должна посчитать факториал вводимого числа, который вы потом захотите сохранить в переменной f. Вот как это не стоит делать:
5
def factorial(n): global f res = 1 for i in range(2, n + 1): res *= i f = res n = int(input()) factorial(n) # дальше всякие действия с переменной f
Этот код написан плохо, потому что его трудно использовать ещё один раз. Если вам завтра понадобится в другой программе использовать функцию «факториал», то вы не сможете просто скопировать эту функцию отсюда и вставить в вашу новую программу. Вам придётся поменять то, как она возвращает посчитанное значение.
Гораздо лучше переписать этот пример так:
5
# начало куска кода, который можно копировать из программы в программу def factorial(n): res = 1 for i in range(2, n + 1): res *= i return res # конец куска кода n = int(input()) f = factorial(n) # дальше всякие действия с переменной f
Если нужно, чтобы функция вернула не одно значение, а два или более, то для этого функция может вернуть список из двух или нескольких значений:
Тогда результат вызова функции можно будет использовать во множественном присваивании:
3. Рекурсия
def short_story(): print("У попа была собака, он ее любил.") print("Она съела кусок мяса, он ее убил,") print("В землю закопал и надпись написал:") short_story()
Как мы видели выше, функция может вызывать другую функцию. Но функция также может вызывать и саму себя! Рассмотрим это на примере функции вычисления факториала. Хорошо известно, что 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. Таким образом, для вычисления факториала мы можем использовать значение факториала для меньшего числа. Это можно сделать и в программе на Питоне:
def factorial(n): if n == 0: return 1 else: return n * factorial(n - 1) print(factorial(5))
Подобный прием (вызов функцией самой себя) называется рекурсией, а сама функция называется рекурсивной.
Рекурсивные функции являются мощным механизмом в программировании. К сожалению, они не всегда эффективны. Также часто использование рекурсии приводит к ошибкам. Наиболее распространенная из таких ошибок – бесконечная рекурсия, когда цепочка вызовов функций никогда не завершается и продолжается, пока не кончится свободная память в компьютере. Пример бесконечной рекурсии приведен в эпиграфе к этому разделу. Две наиболее распространенные причины для бесконечной рекурсии:
- Неправильное оформление выхода из рекурсии. Например, если мы в программе вычисления факториала
забудем поставить проверку
if n == 0
, тоfactorial(0)
вызоветfactorial(-1)
, тот вызоветfactorial(-2)
и т. д. - Рекурсивный вызов с неправильными параметрами. Например, если функция
factorial(n)
будет вызыватьfactorial(n)
, то также получится бесконечная цепочка.
Поэтому при разработке рекурсивной функции необходимо прежде всего оформлять условия завершения рекурсии и думать, почему рекурсия когда-либо завершит работу.
Ссылки на задачи доступны в меню слева. Эталонные решения теперь доступны на странице самой задачи.
Функции в программировании. Курс «Python. Введение в программирование»
Функция в программировании представляет собой обособленный участок кода, который можно вызывать, обратившись к нему по имени, которым он был назван. При вызове происходит выполнение команд тела функции.
Функции можно сравнить с небольшими программками, которые сами по себе, то есть автономно, не исполняются, а встраиваются в обычную программу. Нередко их так и называют – подпрограммы. Других ключевых отличий функций от программ нет. Функции также при необходимости могут получать и возвращать данные. Только обычно они их получают не с ввода (клавиатуры, файла и др.), а из вызывающей программы. Сюда же они возвращают результат своей работы.
Существует множество встроенных в язык программирования функций. С некоторыми такими в Python мы уже сталкивались. Это print()
, input()
, int()
, float()
, str()
, type()
. Код их тела нам не виден, он где-то «спрятан внутри языка». Нам же предоставляется только интерфейс – имя функции.
С другой стороны, программист всегда может определять свои функции. Их называют пользовательскими. В данном случае под «пользователем» понимают программиста, а не того, кто пользует программу. Разберемся, зачем нам эти функции, и как их создавать.
Предположим, надо три раза подряд запрашивать на ввод пару чисел и складывать их. С этой целью можно использовать цикл:
i = 0 while i < 3: a = int(input()) b = int(input()) print(a+b) i += 1
Однако, что если перед каждым запросом чисел, надо выводить надпись, зачем они нужны, и каждый раз эта надпись разная. Мы не можем прервать цикл, а затем вернуться к тому же циклу обратно. Придется отказаться от него, и тогда получится длинный код, содержащий в разных местах одинаковые участки:
print("Сколько бананов и ананасов для обезьян?") a = int(input()) b = int(input()) print("Всего", a+b, "шт.") print("Сколько жуков и червей для ежей?") a = int(input()) b = int(input()) print("Всего", a+b, "шт.") print("Сколько рыб и моллюсков для выдр?") a = int(input()) b = int(input()) print("Всего", a+b, "шт.")
Пример исполнения программы:
Сколько бананов и ананасов для обезьян? 15 5 Всего 20 шт. Сколько жуков и червей для ежей? 50 12 Всего 62 шт. Сколько рыб и моллюсков для выдр? 16 8 Всего 24 шт.
Внедрение функций позволяет решить проблему дублирования кода в разных местах программы. Благодаря им можно исполнять один и тот же участок кода не сразу, а только тогда, когда он понадобится.
Определение функции. Оператор def
В языке программирования Python функции определяются с помощью оператора def
. Рассмотрим код:
def countFood(): a = int(input()) b = int(input()) print("Всего", a+b, "шт.")
Это пример определения функции. Как и другие сложные инструкции вроде условного оператора и циклов функция состоит из заголовка и тела. Заголовок оканчивается двоеточием и переходом на новую строку. Тело имеет отступ.
Ключевое слово def
сообщает интерпретатору, что перед ним определение функции. За def
следует имя функции. Оно может быть любым, также как и всякий идентификатор, например, переменная. В программировании весьма желательно давать всему осмысленные имена. Так в данном случае функция названа «посчитатьЕду» в переводе на русский.
После имени функции ставятся скобки. В приведенном примере они пустые. Это значит, что функция не принимает никакие данные из вызывающей ее программы. Однако она могла бы их принимать, и тогда в скобках были бы указаны так называемые параметры.
После двоеточия следует тело, содержащее инструкции, которые выполняются при вызове функции. Следует различать определение функции и ее вызов. В программном коде они не рядом и не вместе. Можно определить функцию, но ни разу ее не вызвать. Нельзя вызвать функцию, которая не была определена. Определив функцию, но ни разу не вызвав ее, вы никогда не выполните ее тела.
Вызов функции
Рассмотрим полную версию программы с функцией:
def countFood(): a = int(input()) b = int(input()) print("Всего", a+b, "шт.") print("Сколько бананов и ананасов для обезьян?") countFood() print("Сколько жуков и червей для ежей?") countFood() print("Сколько рыб и моллюсков для выдр?") countFood()
После вывода на экран каждого информационного сообщения осуществляется вызов функции, который выглядит просто как упоминание ее имени со скобками. Поскольку в функцию мы ничего не передаем скобки опять же пустые. В приведенном коде функция вызывается три раза.
Когда функция вызывается, поток выполнения программы переходит к ее определению и начинает исполнять ее тело. После того, как тело функции исполнено, поток выполнения возвращается в основной код в то место, где функция вызывалась. Далее исполняется следующее за вызовом выражение.
В языке Python определение функции должно предшествовать ее вызовам. Это связано с тем, что интерпретатор читает код строка за строкой и о том, что находится ниже по течению, ему еще неизвестно. Поэтому если вызов функции предшествует ее определению, то возникает ошибка (выбрасывается исключение NameError
):
print("Сколько бананов и ананасов для обезьян?") countFood() print("Сколько жуков и червей для ежей?") countFood() print("Сколько рыб и моллюсков для выдр?") countFood() def countFood(): a = int(input()) b = int(input()) print("Всего", a+b, "шт.")
Результат:
Сколько бананов и ананасов для обезьян? Traceback (most recent call last): File "test.py", line 2, in <module> countFood() NameError: name 'countFood' is not defined
Для многих компилируемых языков это не обязательное условие. Там можно определять и вызывать функцию в произвольных местах программы. Однако для удобочитаемости кода программисты даже в этом случае предпочитают соблюдать определенные правила.
Функции придают программе структуру
Польза функций не только в возможности многократного вызова одного и того же кода из разных мест программы. Не менее важно, что благодаря им программа обретает истинную структуру. Функции как бы разделяют ее на обособленные части, каждая из которых выполняет свою конкретную задачу.
Пусть надо написать программу, вычисляющую площади разных фигур. Пользователь указывает, площадь какой фигуры он хочет вычислить. После этого вводит исходные данные. Например, длину и ширину в случае прямоугольника. Чтобы разделить поток выполнения на несколько ветвей, следует использовать оператор if-elif-else:
figure = input("1-прямоугольник, 2-треугольник, 3-круг: ") if figure == '1': a = float(input("Ширина: ")) b = float(input("Высота: ")) print("Площадь: %.2f" % (a*b)) elif figure == '2': a = float(input("Основание: ")) h = float(input("Высота: ")) print("Площадь: %.2f" % (0.5 * a * h)) elif figure == '3': r = float(input("Радиус: ")) print("Площадь: %.2f" % (3.14 * r**2)) else: print("Ошибка ввода")
Здесь нет никаких функций, и все прекрасно. Но напишем вариант с функциями:
def rectangle(): a = float(input("Ширина: ")) b = float(input("Высота: ")) print("Площадь: %.2f" % (a*b)) def triangle(): a = float(input("Основание: ")) h = float(input("Высота: ")) print("Площадь: %.2f" % (0.5 * a * h)) def circle(): r = float(input("Радиус: ")) print("Площадь: %.2f" % (3.14 * r**2)) figure = input("1-прямоугольник, 2-треугольник, 3-круг: ") if figure == '1': rectangle() elif figure == '2': triangle() elif figure == '3': circle() else: print("Ошибка ввода")
Он кажется сложнее, а каждая из трех функций вызывается всего один раз. Однако из общей логики программы как бы убраны и обособлены инструкции для нахождения площадей. Программа теперь состоит из отдельных «кирпичиков Лего». В основной ветке мы можем комбинировать их как угодно. Она играет роль управляющего механизма.
Если нам когда-нибудь захочется вычислять площадь треугольника по формуле Герона, а не через высоту, то не придется искать код во всей программе (представьте, что она состоит из тысяч строк кода как реальные программы). Мы пойдем к месту определения функций и изменим тело одной из них.
Если понадобиться использовать эти функции в какой-нибудь другой программе, то мы сможем импортировать их туда, сославшись на данный файл с кодом (как это делается в Python, будет рассмотрено позже).
Практическая работа
В программировании можно из одной функции вызывать другую. Для иллюстрации этой возможности напишите программу по следующему описанию.
Основная ветка программы, не считая заголовков функций, состоит из одной строки кода. Это вызов функции test()
. В ней запрашивается на ввод целое число. Если оно положительное, то вызывается функция positive()
, тело которой содержит команду вывода на экран слова «Положительное». Если число отрицательное, то вызывается функция negative()
, ее тело содержит выражение вывода на экран слова «Отрицательное».
Понятно, что вызов test()
должен следовать после определения функций. Однако имеет ли значение порядок определения самих функций? То есть должны ли определения positive()
и negative()
предшествовать test()
или могут следовать после него? Проверьте вашу гипотезу, поменяв объявления функций местами. Попробуйте объяснить результат.
Примеры решения и дополнительные уроки в android-приложении и pdf-версии курса
Функции Python: 7 примеров. Базовые, встроенные и пользовательские функции
В этой статье мы просто приведём практические примеры работы функций в Python. Рассмотрим базовые, встроенные и пользовательские функции, а также функции с параметрами, возвращаемым значением и типом данных.
Функции в Python представляют собой фрагменты кода в блоке, который имеет назначенное имя. Функции принимают ввод, осуществляют вычисления либо какое-нибудь действие и возвращают вывод. И, разумеется, функции упрощают работу с кодом, делая возможным его повторное использование.
Базовые функции Python
Давайте рассмотрим пример функции Python, принимающей 2 параметра, а также вычисляющей сумму и возвращающей вычисленное значение:
#определяем и объявляем функцию def calculate_sum(a,b): sum = a+b return sum #инструкция, приведённая ниже, называется вызовом функции print(calculate_sum(2,3)) # 5
Кроме того, в Python есть встроенные и пользовательские функции.
Пользовательские функции Python
Объявление пользовательской функции осуществляется с применением ключевого слова def. При этом оно должно сопровождаться именем пользовательской функции:
def calculate_si_amount(principal, rate, time): interest = (principal*rate*time)/100 return principal+interest
В данной функции окончательная сумма может быть рассчитана посредством использования простого процента к основной сумме. Именем функции является Calculate_si_amount. Что касается principal, time и rate — то это параметры, а функция возвращает рассчитанные данные.
Для пользовательской функции можно не принимать возвращаемые значения и параметры. На нижеследующем примере мы видим пользовательскую функцию, не принимающую никаких параметров, зато возвращающую данные.
from random import seed, random from random import random def generate_random_number(): seed(10) return random()
Встроенные функции Python
В Python существует много встроенных функций. Одна из наиболее часто используемых — print(). Её работа чрезвычайно проста:
print("Всем привет") print(len("Меня зовут Андрей"))
Ещё популярны такие функции, как len(),abs(), sum(), str(), int() и другие.
Параметры функции в Python
В языке программирования Python функция может иметь параметры по умолчанию:
def multiply(a, b=10): return a*b multiply(12) # 120 multiply(2, 3) # 6 multiply(b=9) # Ошибка: None*9 недопустимо
В вышеописанной функции, когда пользователь не задает 2-й параметр b, он предполагает, что параметр равен 10, однако при этом нужно предоставить 1-й параметр.
Неизвестное количество параметров в функции Python
Когда в функции, допустим, четыре параметра, а для второго параметра определено значение по умолчанию, то третьему и четвёртому параметрам тоже необходимо присвоить значение по умолчанию.
Когда число параметров неизвестно, тогда в определение функции в качестве одного из параметров добавляется *args. Данный параметр ожидает кортеж. В нашем случае звёздочка (*) очень важна, т. к. название args просто является соглашением, то есть можно дать любое другое имя.
def calculate_sum(a, *args): sum = a for i in args: sum += i return sum calculate_sum(10) # 10 calculate_sum(10, 11, 12) # 33 calculate_sum(1, 2, 94, 6, 2, 8, 9, 20, 43, 2) # 187
Так же **kwargs ожидает словарь в качестве параметра.
def print_names(f1, l1, **kwargs): print(f1, l1, end=' ') for key in kwargs: print(key, kwargs[key], end=' ') print_names("andrey", "master") print_names("andrey", "master", alex="john", leon="elene") # andrey master andrey master alex john leon elene
Обратите внимание, что фрагмент выше имеет ссылку на цикл for.
Тип данных для возвращаемого значения и параметров в Python
Определение типов данных для параметров функции в Python может быть полезным:
def prime_numbers(x:int) -> (int, list): l=[] for i in range(x+1): if checkPrime(i): l.append(i) return len(l), l
В нашем примере определение функции указывает, что нужен 1 параметр типа int и вернёт два значения типа list и int соответственно.
Возвращаемое значение функции в Python
Язык программирования Python даёт возможность функции возвращать несколько значений.
def prime_numbers(x): l=[] for i in range(x+1): if checkPrime(i): l.append(i) return len(l), l no_of_primes, primes_list = prime_numbers(100)
В нашем случае возвращаются 2 значения. Если данная функция вызывается, то возвращаемые значения сохраняются одновременно в 2-х переменных. Если же функция не возвращает ничего, то она неявно возвращает None.
PostgreSQL : Документация: 9.6: 44.2. Функции на PL/Python : Компания Postgres Professional
44.2. Функции на PL/Python
Функции на PL/Python объявляются стандартным образом с помощью команды CREATE FUNCTION:
CREATE FUNCTIONfuncname
(argument-list
) RETURNSreturn-type
AS $$ # Тело функции на PL/Python $$ LANGUAGE plpythonu;
Тело функции содержит просто скрипт на языке Python. Когда вызывается функция, её аргументы передаются в виде элементов списка args
; именованные аргументы также передаются скрипту Python как обычные переменные. С применением именованных аргументов скрипт обычно лучше читается. Результат из кода Python возвращается обычным способом, командой return
или yield
(в случае функции, возвращающей множество). Если возвращаемое значение не определено, Python возвращает None
. Исполнитель PL/Python преобразует None
языка Python в значение NULL языка SQL.
Например, функцию, возвращающее большее из двух целых чисел, можно определить так:
CREATE FUNCTION pymax (a integer, b integer) RETURNS integer AS $$ if a > b: return a return b $$ LANGUAGE plpythonu;
Код на Python, заданный в качестве тела объявляемой функции, становится телом функции Python. Например, для показанного выше объявления получается функция:
def __plpython_procedure_pymax_23456(): if a > b: return a return b
Здесь 23456 — это OID, который PostgreSQL присвоил данной функции.
Значения аргументов задаются в глобальных переменных. Согласно правилам видимости в Python, тонким следствием этого является то, что переменной аргумента нельзя присвоить внутри функции выражение, включающее имя самой этой переменной, если только эта переменная не объявлена глобальной в текущем блоке. Например, следующий код не будет работать:
CREATE FUNCTION pystrip(x text) RETURNS text AS $$ x = x.strip() # ошибка return x $$ LANGUAGE plpythonu;
так как присвоение x
значения делает x
локальной переменной для всего блока, и при этом x
в правой части присваивания оказывается ещё не определённой локальной переменной x
, а не параметром функции PL/Python. Добавив оператор global
, это можно исправить:
CREATE FUNCTION pystrip(x text) RETURNS text AS $$ global x x = x.strip() # теперь всё в порядке return x $$ LANGUAGE plpythonu;
Однако рекомендуется не полагаться на такие особенности реализации PL/Python, а принять, что параметры функции предназначены только для чтения.
функций Python
Функция — это блок кода, который выполняется только при вызове.
В функцию можно передавать данные, называемые параметрами.
В результате функция может возвращать данные.
Создание функции
В Python функция определяется с использованием def ключевое слово:
Пример
def my_function ():
print («Привет от функции»)
Вызов функции
Чтобы вызвать функцию, используйте имя функции, за которым следует скобка:
Пример
def my_function ():print («Привет от функции»)
my_function ()
Попробуй сам »Аргументы
Информация может передаваться в функции как аргументы.
Аргументы указываются после имени функции в круглых скобках. Вы можете добавить сколько угодно аргументов, просто разделив их запятыми.
В следующем примере есть функция с одним аргументом (fname). Когда функция вызывается, мы передаем имя, который используется внутри функции для вывода полного имени:
Пример
def my_function ( fname ):print (fname + «Refsnes»)
my_function ( «Emil» )
my_function ( «Tobias» )
my_function ( «Linus» )
Аргументы часто сокращаются до args в документации Python.
Параметры или аргументы?
Термины параметр и аргумент могут использоваться для одного и того же: информации, которая передается в функцию.
С точки зрения функции:
Параметр — это переменная, указанная в скобках в определении функции.
Аргумент — это значение, которое отправляется функции при ее вызове.
Количество аргументов
По умолчанию функция должна вызываться с правильным количеством аргументов.Это означает, что если ваша функция ожидает 2 аргумента, вы должны вызвать функцию с 2 аргументами, не больше и не меньше.
Пример
Эта функция ожидает 2 аргумента и получает 2 аргумента:
def my_function (fname, lname):print (fname + «» + lname)
my_function («Emil», «Refsnes»)
Попробуй сам » Если вы попытаетесь вызвать функцию с 1 или 3 аргументами, вы получите ошибку:Пример
Эта функция ожидает 2 аргумента, но получает только 1:
def my_function (fname, lname):print (fname + «» + lname)
my_function («Emil»)
Попробуй сам »Произвольные аргументы, * args
Если вы не знаете, сколько аргументов будет передано вашей функции,
добавьте *
перед именем параметра в определении функции.
Таким образом, функция получит кортеж аргументов и сможет получить доступ к элементам соответственно:
Пример
Если количество аргументов неизвестно, добавьте перед именем параметра *
:
print («Самый младший ребенок is «+ kids [2])
my_function (» Эмиль «,» Тобиас «,» Линус «)
Попробуй сам »Произвольные аргументы часто сокращаются до * args в документации Python.
Аргументы ключевого слова
Вы также можете отправлять аргументы с синтаксисом ключ = значение .
Таким образом, порядок аргументов не имеет значения.
Пример
def my_function (child3, child2, child1):print («Самый младший ребенок is «+ child3)
my_function (child1 =» Emil «, child2 =» Tobias «, child3 =» Linus «)
Попробуй сам »Фраза Аргументы ключевого слова часто сокращается до kwargs в документации Python.
Аргументы произвольного ключевого слова, ** kwargs
Если вы не знаете, сколько аргументов ключевого слова будет передано вашей функции,
добавьте две звездочки: **
перед именем параметра в определении функции.
Таким образом, функция получит словарь аргументов и сможет получить доступ к элементам соответственно:
Пример
Если количество аргументов ключевого слова неизвестно, добавьте двойной **
перед именем параметра:
print («Его фамилия» + kid [«lname»])
my_function (fname = «Tobias», lname = «Refsnes»)
Попробуй сам »Произвольные аргументы Kword часто сокращаются до ** kwargs в документации Python.
Значение параметра по умолчанию
В следующем примере показано, как использовать значение параметра по умолчанию.
Если мы вызываем функцию без аргументов, она использует значение по умолчанию:
Пример
def my_function ( country = «Норвегия» ):print («Я из» + страна)
my_function («Швеция»)
my_function («Индия»)
my_function ()
my_function («Бразилия»)
Передача списка в качестве аргумента
Вы можете отправлять аргументы любых типов данных функции (строка, число, список, словарь и т. Д.).), и это будет обрабатываться как один и тот же тип данных внутри функции.
Например, если вы отправите список в качестве аргумента, он все равно будет списком, когда он достигает функции:
Пример
def my_function (food):для x в food:
print (x)
fruit = [«яблоко», «банан», «вишня»]
my_function (fruit)
Возвращаемые значения
Чтобы функция возвращала значение, используйте возврат
выписка:
Пример
def my_function (x):
return 5 * x
print (my_function (3))
print (my_function (5))
print (my_function (9))
Пропуск Заявление
определение функции
не может быть пустым, но если
у вас по какой-то причине есть определение функции
без содержимого, введите оператор pass
, чтобы избежать ошибки.
Рекурсия
Python также принимает рекурсию функций, что означает, что определенная функция может вызывать сама себя.
Рекурсия — это общая математическая и программная концепция. Это означает, что функция вызывает сама себя. Это имеет то преимущество, что вы можете перебирать данные для достижения результата.
Разработчику следует быть очень осторожным с рекурсией, поскольку довольно легко ускользнуть от написания функции, которая никогда не завершается, или функции, которая использует избыточные объемы памяти или мощности процессора.Однако при правильном написании рекурсия может быть очень эффективным и математически элегантным подходом к программированию.
В этом примере tri_recursion () — это функция, которую мы определили для вызова самой себя («рекурсивная»). Мы используем переменную k в качестве данных, которая уменьшается на (-1) каждый раз, когда мы выполняем рекурсию. Рекурсия заканчивается, когда условие не больше 0 (т.е. когда оно равно 0).
Новому разработчику может потребоваться некоторое время, чтобы понять, как именно это работает, лучший способ выяснить это — протестировать и изменить его.
Пример
Пример рекурсии
def tri_recursion (k):если (k> 0):
результат = k + tri_recursion (k — 1)
print (результат)
еще:
результат = 0
вернуть результат
print («\ n \ nRecursion Example Results»)
tri_recursion (6)
Python Лямбда
Лямбда-функция — это небольшая анонимная функция.
Лямбда-функция может принимать любое количество аргументов, но может иметь только одно выражение.
Синтаксис
лямбда аргументы : выражение
Выражение выполняется и возвращается результат:
Пример
Добавьте 10 к аргументу a
, и
вернуть результат:
x = лямбда a: a + 10
печать (x (5))
Лямбда-функции могут принимать любое количество аргументов:
Пример
Умножить аргумент на
на аргумент b
и верните
результат:
x = лямбда a, b: a * b
print (x (5, 6))
Пример
Обобщить аргумент a
, b
и c
и
вернуть
результат:
x = лямбда a, b, c: a + b + c
print (x (5, 6,
2))
Зачем нужны лямбда-функции?
Сила лямбда лучше проявляется, когда вы используете их как анонимные. функция внутри другой функции.
Допустим, у вас есть определение функции, которое принимает один аргумент, и этот аргумент будет умножено на неизвестное число:
def myfunc (n):
вернуть лямбда a: a * n
Используйте это определение функции, чтобы создать функцию, которая всегда удваивает номер, который вы отправляете:
Пример
определение myfunc (n):вернуть лямбда a: a * n
mydoubler = myfunc (2)
print (mydoubler (11))
Попробуй сам »Или используйте то же определение функции, чтобы создать функцию, которая всегда утроит номер, который вы отправляете:
Пример
определение myfunc (n):вернуть лямбда a: a * n
mytripler = myfunc (3)
print (mytripler (11))
Попробуй сам »Или используйте одно и то же определение функции, чтобы сделать обе функции в одном программа:
Пример
определение myfunc (n):вернуть лямбда a: a * n
mydoubler = myfunc (2)
mytripler = myfunc (3)
print (mydoubler (11))
принт (mytripler (11))
Используйте лямбда-функции, когда анонимная функция требуется на короткий период времени.
Встроенные функции — документация Python 3.9.6
Откройте файл и верните соответствующий файловый объект. Если файл
не может быть открыт, возникает ошибка OSError
. Видеть
Чтение и запись файлов для получения дополнительных примеров использования этой функции.
файл — это объект, похожий на путь, дающий имя пути (абсолютное или
относительно текущего рабочего каталога) открываемого файла или
целочисленный файловый дескриптор файла, который нужно обернуть.(Если дескриптор файла
задано, он закрывается, когда возвращенный объект ввода-вывода закрывается, если только closefd установлен на Ложь
.)
режим — дополнительная строка, указывающая режим, в котором файл
открыт. По умолчанию это 'r'
, что означает открытие для чтения в текстовом режиме.
Другие общие значения: 'w'
для записи (усечение файла, если он
уже существует), 'x'
для исключительного создания и 'a'
для добавления
(что на некоторых системах Unix означает, что все записи добавляются в конец
файл независимо от текущей позиции поиска).В текстовом режиме, если
Кодировка не указана, используемая кодировка зависит от платформы: locale.getpreferredencoding (False)
вызывается для получения текущей локали
кодирование. (Для чтения и записи сырых байтов используйте двоичный режим и оставьте кодировка не указана.) Доступные режимы:
Знак | Значение |
---|---|
| открыто для чтения (по умолчанию) |
| открыт для записи, сначала обрезка файла |
| открыто для монопольного создания, ошибка, если файл уже существует |
| открыто для записи, добавляется в конец файла, если он существует |
| двоичный режим |
| текстовый режим (по умолчанию) |
| открыт для обновления (чтение и запись) |
Режим по умолчанию — 'r'
(открыт для чтения текста, синоним 'rt'
).Режимы 'w +'
и 'w + b'
открывают и обрезают файл. Режимы 'r +'
и 'r + b'
открывают файл без усечения.
Как упоминалось в обзоре, Python различает двоичные
и текстовый ввод / вывод. Файлы, открытые в двоичном режиме (включая 'b'
в режиме аргумент) возвращает содержимое как байтов
объектов без какого-либо декодирования. В
текстовый режим (по умолчанию или когда 't'
включен в аргумент mode ),
содержимое файла возвращается как str
, байты были
сначала декодируется с использованием платформенно-зависимого кодирования или с использованием указанного кодирование , если указано.
Разрешен дополнительный символ режима, 'U'
, который больше не
имеет какой-либо эффект и считается устаревшим. Ранее он был включен
универсальные символы новой строки в текстовом режиме, которые стали поведением по умолчанию
в Python 3.0. См. Документацию к
параметр новой строки для получения дополнительных сведений.
Примечание
Python не зависит от представления текста операционной системой. файлы; вся обработка выполняется самим Python и, следовательно, независимая платформа.
буферизация — необязательное целое число, используемое для установки политики буферизации. Пройти 0 для выключения буферизации (разрешено только в двоичном режиме), 1 для выбора строки буферизация (может использоваться только в текстовом режиме) и целое число> 1, чтобы указать размер в байтах буфера фрагментов фиксированного размера. Когда нет буферизации аргумент Учитывая, что политика буферизации по умолчанию работает следующим образом:
Двоичные файлы буферизуются фрагментами фиксированного размера; размер буфера выбирается с помощью эвристики, пытающейся определить «блокировку» основного устройства размер »и возвращается к
io.DEFAULT_BUFFER_SIZE
. Во многих системах размер буфера обычно составляет 4096 или 8192 байта.«Интерактивные» текстовые файлы (файлы, для которых
isatty ()
возвращаетИстина
) использовать буферизацию строки. Другие текстовые файлы используют политику описано выше для двоичных файлов.
кодировка — это имя кодировки, используемой для декодирования или кодирования файла.
Это следует использовать только в текстовом режиме. Кодировка по умолчанию — платформа.
зависимый (независимо от локали .getpreferredencoding ()
возвращает), но любой
кодировка текста, поддерживаемая Python
может быть использован. См. Модуль кодеков
для
список поддерживаемых кодировок.
ошибок — необязательная строка, определяющая способ кодирования и декодирования.
ошибки должны обрабатываться — это не может использоваться в двоичном режиме.
Доступны различные стандартные обработчики ошибок.
(перечислены в разделе «Обработчики ошибок»), хотя любые
имя обработки ошибок, которое было зарегистрировано с codecs.register_error ()
также допустим.Стандартные имена
включают:
'strict'
, чтобы вызвать исключениеValueError
, если есть ошибка кодировки. Значение по умолчаниюНет
имеет то же самое эффект.'ignore'
игнорирует ошибки. Обратите внимание, что игнорирование ошибок кодирования может привести к потере данных.'replace'
вызывает вставку маркера замены (например,'?'
) где есть искаженные данные.'surrogateescape'
будет представлять любые неправильные байты как код точек в области частного использования Unicode в диапазоне от U + DC80 до U + DCFF.Эти частные кодовые точки будут затем снова превращены в те же байты при использовании обработчика ошибок суррогатапри записи данных. Это полезно для обработки файлов в неизвестная кодировка.
'xmlcharrefreplace'
поддерживается только при записи в файл. Символы, не поддерживаемые кодировкой, заменяются символами ссылка на соответствующий символ XML& # nnn;
.'backslashreplace'
заменяет искаженные данные на обратную косую черту Python escape-последовательности.'namereplace'
(также поддерживается только при записи) заменяет неподдерживаемые символы управляющими последовательностями\ N {...}
.
новая строка управляет тем, как работает универсальный режим новой строки (только
относится к текстовому режиму). Это может быть None
, ''
, '\ n'
, '\ r'
и '\ r \ n'
. Работает следующим образом:
При чтении ввода из потока, если перевод строки равен
Нет
, универсальный Режим новой строки включен.Строки на входе могут заканчиваться на'\ n'
,'\ r'
или'\ r \ n'
, и они переводятся в'\ n'
перед возвращаются вызывающему абоненту. Если это''
, универсальный режим новой строки включен, но окончания строк возвращаются вызывающему абоненту без перевода. Если это имеет любое из других допустимых значений, строки ввода заканчиваются только заданная строка, и конец строки возвращается вызывающему абоненту без перевода.При записи вывода в поток, если новая строка - это
Нет
, любое'\ n'
написанные символы переводятся в системный разделитель строк по умолчанию,ос.linesep
. Если новая строка -''
или'\ n'
, перевода нет происходит. Если новая строка - любое другое допустимое значение, любое'\ n'
написанные символы переводятся в заданную строку.
Если closefd - Ложь
и был указан дескриптор файла, а не имя файла.
задано, базовый дескриптор файла будет оставаться открытым, когда файл
закрыто. Если указано имя файла closefd должно быть True
(по умолчанию)
в противном случае возникнет ошибка.
Можно использовать настраиваемый открыватель, передав вызываемый объект как opener . Лежащий в основе
файловый дескриптор для файлового объекта затем получается путем вызова открывателя с
( файл , флаги ). открыватель должен возвращать дескриптор открытого файла (передавая os.open
as opener приводит к функциональности, аналогичной прохождению Нет
).
Вновь созданный файл не наследуется.
В следующем примере используется параметр dir_fd ос.open ()
, чтобы открыть файл, относящийся к заданному каталогу:
>>> импорт ос >>> dir_fd = os.open ('somedir', os.O_RDONLY) >>> def opener (путь, флаги): ... вернуть os.open (путь, флаги, dir_fd = dir_fd) ... >>> с open ('spamspam.txt', 'w', opener = opener) как f: ... print ('Это будет записано в somedir / spamspam.txt', file = f) ... >>> os.close (dir_fd) # не допускать утечки файлового дескриптора
Тип файлового объекта, возвращаемого функцией open ()
зависит от режима.Когда open ()
используется для открытия файла в тексте
режим ( 'w'
, 'r'
, 'wt'
, 'rt'
и т. д.), он возвращает подкласс io.TextIOBase
(в частности, io.TextIOWrapper
). При использовании
чтобы открыть файл в двоичном режиме с буферизацией, возвращаемый класс -
подкласс io.BufferedIOBase
. Точный класс варьируется: в прочтении
двоичный режим, он возвращает io.BufferedReader
; в записи двоичного кода и
добавить двоичные режимы, он возвращает io.BufferedWriter
, а в
режим чтения / записи, он возвращает io.BufferedRandom
. Когда буферизация
отключен, необработанный поток, подкласс io.RawIOBase
, io.FileIO
, возвращается.
См. Также модули обработки файлов, например, fileinput
, io
(где объявлен open ()
), os
, os.path
, tempfile
,
и шутил
.
Вызывает событие аудита открыть
с аргументами файл
, режим
, флаги
.
Режим
и флаги аргументы
могли быть изменены или выведены из
исходный звонок.
Изменено в версии 3.3:
Добавлен параметр открывателя .
Добавлен режим
'x'
.Вызывалось
IOError
, теперь это псевдонимOSError
.
FileExistsError
теперь возникает, если файл открывается в монопольном режиме. режим создания ('x'
) уже существует.
Устарело с версии 3.4, будет удалено в версии 3.10: режим 'U'
.
Изменено в версии 3.5:
Если системный вызов прерывается и обработчик сигнала не вызывает исключение, функция теперь повторяет системный вызов вместо того, чтобы вызывать
InterruptedError
исключение (объяснение см. В PEP 475 ).Добавлен обработчик ошибок
namereplace
.
Python-функций (def): определение с примерами
Что такое функция в Python?
В Python функция - это группа связанных операторов, выполняющих определенную задачу.
Функции помогают разбить нашу программу на более мелкие и модульные части. По мере того, как наша программа становится все больше и больше, функции делают ее более организованной и управляемой.
Кроме того, он позволяет избежать повторения и позволяет многократно использовать код.
Синтаксис функции
def имя_функции (параметры): "" "строка документации" "" выписка (а)
Выше показано определение функции, состоящее из следующих компонентов.
- Ключевое слово
def
, которое отмечает начало заголовка функции. - Имя функции, однозначно идентифицирующее функцию. Именование функций следует тем же правилам написания идентификаторов в Python.
- Параметры (аргументы), через которые мы передаем значения функции. Они не обязательны.
- Двоеточие (:) для обозначения конца заголовка функции.
- Необязательная строка документации (docstring), описывающая, что делает функция.
- Один или несколько допустимых операторов Python, составляющих тело функции.Заявления должны иметь одинаковый уровень отступа (обычно 4 пробела).
- Необязательный оператор
return
для возврата значения из функции.
Пример функции
def greet (имя):
"" "
Эта функция приветствует
человек прошел как
параметр
"" "
print («Привет,» + имя + «. Доброе утро!»)
Как вызвать функцию в Python?
После того, как мы определили функцию, мы можем вызвать ее из другой функции, программы или даже из командной строки Python.Чтобы вызвать функцию, мы просто вводим имя функции с соответствующими параметрами.
>>> привет ('Павел')
Привет, Пол. Доброе утро!
Примечание: Попробуйте запустить приведенный выше код в программе Python с определением функции, чтобы увидеть результат.
def greet (имя):
"" "
Эта функция приветствует
человек прошел как
параметр
"" "
print ("Привет," + имя + ". Доброе утро!")
привет ('Павел')
Строки документации
Первая строка после заголовка функции называется строкой документации и является сокращением от строки документации.Он кратко используется для объяснения того, что делает функция.
Хотя документация не является обязательной, это хорошая практика программирования. Если вы не помните, что ели на ужин на прошлой неделе, всегда документируйте свой код.
В приведенном выше примере у нас есть строка документации непосредственно под заголовком функции. Обычно мы используем тройные кавычки, чтобы строка документа могла занимать несколько строк. Эта строка доступна нам как атрибут функции __doc__
.
Например :
Попробуйте запустить в оболочке Python следующую команду, чтобы увидеть результат.
>>> печать (привет .__ doc__)
Эта функция приветствует
человек прошел как
параметр
Чтобы узнать больше о строках документации в Python, посетите страницу Python Docstrings.
Отчет о возврате
Оператор return
используется для выхода из функции и возврата в то место, откуда она была вызвана.
Синтаксис возврата
возврат [список_выражений]
Этот оператор может содержать выражение, которое вычисляется и возвращается значение.Если в операторе нет выражения или сам оператор return
отсутствует внутри функции, тогда функция вернет объект None
.
Например:
>>> print (привет («май»))
Привет, май. Доброе утро!
Нет
Здесь None
- это возвращаемое значение, поскольку greet ()
напрямую печатает имя, а оператор return
не используется.
Пример возврата
def absolute_value (число):
"" "Эта функция возвращает абсолютное
значение введенного числа "" "
если число> = 0:
вернуть номер
еще:
return -num
печать (абсолютное_значение (2))
печать (абсолютное_значение (-4))
Выход
2 4
Как функция работает в Python?
Работа функций в PythonОбъем и время жизни переменных
Объем переменной - это часть программы, в которой переменная распознается.Параметры и переменные, определенные внутри функции, не видны снаружи функции. Следовательно, они имеют локальный охват.
Время жизни переменной - это период, в течение которого переменная находится в памяти. Время жизни переменных внутри функции - до тех пор, пока функция выполняется.
Они уничтожаются, когда мы возвращаемся из функции. Следовательно, функция не запоминает значение переменной из своих предыдущих вызовов.
Вот пример, иллюстрирующий область действия переменной внутри функции.
def my_func ():
х = 10
print ("Значение внутри функции:", x)
х = 20
my_func ()
print ("Значение вне функции:", x)
Выход
Значение внутри функции: 10 Значение вне функции: 20
Здесь мы видим, что значение x изначально равно 20. Несмотря на то, что функция my_func ()
изменила значение x на 10, это не повлияло на значение вне функции.
Это связано с тем, что переменная x внутри функции отличается (локальная для функции) от переменной снаружи.Хотя у них одинаковые имена, это две разные переменные с разными областями действия.
С другой стороны, переменные вне функции видны изнутри. У них глобальный размах.
Мы можем читать эти значения изнутри функции, но не можем их изменять (записывать). Чтобы изменить значение переменных вне функции, они должны быть объявлены как глобальные переменные с использованием ключевого слова global
.
Типы функций
В принципе, мы можем разделить функции на следующие два типа:
- Встроенные функции - Функции, встроенные в Python.
- Пользовательские функции - Функции, определяемые самими пользователями.
Определение вашей собственной функции Python - Настоящий Python
Смотреть сейчас Это руководство содержит соответствующий видеокурс, созданный командой Real Python. Просмотрите его вместе с письменным руководством, чтобы углубить свое понимание: Определение и вызов функций Python
На протяжении предыдущих руководств этой серии вы видели множество примеров, демонстрирующих использование встроенных функций Python.В этом руководстве вы узнаете, как определить вашу собственную функцию Python . Вы узнаете, когда разделить вашу программу на отдельные пользовательские функции и какие инструменты вам понадобятся для этого.
Из этого руководства вы узнаете:
- Как функции работают в Python и почему они полезны
- Как определить и вызвать вашу собственную функцию Python
- Механизмы передачи аргументов вашей функции
- Как вернуть данные из вашей функции обратно в вызывающую среду
Функции в Python
Возможно, вы знакомы с математической концепцией функции .Функция - это связь или отображение между одним или несколькими входами и набором выходов. В математике функция обычно представлена так:
Здесь f
- это функция, которая работает на входах x
и y
. Результатом функции будет z
. Однако функции программирования гораздо более обобщены и универсальны, чем это математическое определение. Фактически, правильное определение и использование функций настолько критично для правильной разработки программного обеспечения, что практически все современные языки программирования поддерживают как встроенные, так и определяемые пользователем функции.
В программировании функция - это автономный блок кода, который инкапсулирует конкретную задачу или связанную группу задач. В предыдущих руководствах этой серии вы познакомились с некоторыми встроенными функциями, предоставляемыми Python. id ()
, например, принимает один аргумент и возвращает уникальный целочисленный идентификатор этого объекта:
>>> s = 'foobar'
>>> id (s)
56313440
len ()
возвращает длину переданного ему аргумента:
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> len (а)
4
any ()
принимает в качестве аргумента итерацию и возвращает Истина
, если какой-либо из элементов в итерации является истинным, и False
в противном случае:
>>> любое ([False, False, False])
Ложь
>>> любой ([Ложь, Истина, Ложь])
Правда
>>> any (['bar' == 'baz', len ('foo') == 4, 'qux' в {'foo', 'bar', 'baz'}])
Ложь
>>> any (['bar' == 'baz', len ('foo') == 3, 'qux' в {'foo', 'bar', 'baz'}])
Правда
Каждая из этих встроенных функций выполняет определенную задачу.Код, выполняющий задачу, где-то определен, но вам не нужно знать, где и даже как он работает. Все, что вам нужно знать, это интерфейс функции:
- Какие аргументов (если есть) нужно
- Какие значения (если есть) он возвращает
Затем вы вызываете функцию и передаете ей соответствующие аргументы. Выполнение программы переходит к обозначенному фрагменту кода и делает свое полезное дело. Когда функция завершена, выполнение возвращается к вашему коду с того места, где оно было остановлено.Функция может возвращать или не возвращать данные для использования вашим кодом, как в приведенных выше примерах.
Когда вы определяете свою собственную функцию Python, она работает точно так же. Где-то в коде вы вызываете функцию Python, и выполнение программы передается в тело кода, составляющего функцию.
Примечание: В этом случае вы будете знать, где находится код и как именно он работает, потому что вы его написали!
Когда функция завершена, выполнение возвращается в то место, где функция была вызвана.В зависимости от того, как вы спроектировали интерфейс функции, данные могут передаваться при вызове функции, а возвращаемые значения могут передаваться обратно после ее завершения.
Важность функций Python
Практически все языки программирования, используемые сегодня, поддерживают определенные пользователем функции, хотя их не всегда называют функциями. На других языках вы можете встретить их как одно из следующих:
- Подпрограммы
- Процедуры
- Методы
- Подпрограммы
Итак, зачем вообще определять функции? Есть несколько очень веских причин.Давайте пройдемся по нескольким.
Абстракция и возможность повторного использования
Предположим, вы пишете код, который делает что-то полезное. По мере продолжения разработки вы обнаружите, что задача, выполняемая этим кодом, вам часто требуется во многих различных местах вашего приложения. Что вы должны сделать? Что ж, вы можете просто копировать код снова и снова, используя возможность копирования и вставки вашего редактора.
Позже вы, вероятно, решите, что рассматриваемый код нужно изменить.Вы либо обнаружите, что с ним что-то не так, что нужно исправить, либо захотите как-то улучшить его. Если копии кода разбросаны по всему приложению, вам нужно будет внести необходимые изменения в каждом месте.
Примечание: На первый взгляд это может показаться разумным решением, но в долгосрочной перспективе это может стать кошмаром для обслуживания! Хотя ваш редактор кода может помочь, предоставляя функцию поиска и замены, этот метод подвержен ошибкам, и вы можете легко внести в свой код ошибки, которые будет трудно найти.
Лучшее решение - это определить функцию Python, которая выполняет задачу . В любом месте вашего приложения, где вам нужно выполнить задачу, вы просто вызываете функцию. В дальнейшем, если вы решите изменить способ работы, вам нужно будет изменить код только в одном месте, то есть в том месте, где определена функция. Изменения будут автоматически приняты везде, где вызывается функция.
Абстракция функциональности в определение функции является примером принципа «не повторяйся» (DRY) при разработке программного обеспечения.Это, пожалуй, самая сильная мотивация для использования функций.
Модульность
Функциипозволяют разбить сложных процессов на более мелкие этапы. Представьте, например, что у вас есть программа, которая читает файл, обрабатывает его содержимое, а затем записывает выходной файл. Ваш код может выглядеть так:
# Основная программа
# Код для чтения файла в
<заявление>
<заявление>
<заявление>
<заявление>
# Код для обработки файла
<заявление>
<заявление>
<заявление>
<заявление>
# Код для записи файла
<заявление>
<заявление>
<заявление>
<заявление>
В этом примере основная программа - это связка кода, связанного в длинную последовательность, с пробелами и комментариями, которые помогают упорядочить ее.Однако, если бы код стал намного длиннее и сложнее, вам было бы все труднее осмыслить его.
В качестве альтернативы вы можете структурировать код примерно так:
def read_file ():
# Код для чтения файла в
<заявление>
<заявление>
<заявление>
<заявление>
def process_file ():
# Код для обработки файла
<заявление>
<заявление>
<заявление>
<заявление>
def write_file ():
# Код для записи файла
<заявление>
<заявление>
<заявление>
<заявление>
# Основная программа
read_file ()
process_file ()
write_file ()
Этот пример - модульный .Вместо того, чтобы связывать весь код вместе, он разбит на отдельные функции, каждая из которых ориентирована на конкретную задачу. Эти задачи: чтение , процесс и запись . Теперь основной программе просто нужно вызвать каждый из них по очереди.
Примечание: Ключевое слово def
вводит новое определение функции Python. Вы все об этом узнаете очень скоро.
В жизни вы делаете такие вещи все время, даже если явно не думаете об этом.Если бы вы захотели переместить несколько полок, заполненных вещами, из одной стороны гаража в другую, то, надеюсь, вы не станете просто стоять и бесцельно думать: «Ой, блин. Мне нужно перевезти все это туда! Как я это сделал???" Вы бы разделили задание на управляемые шаги:
- Уберите все с полок.
- Разобрать полки.
- Перенесите части полки через гараж на новое место.
- Снова соберите полки.
- Перенести вещей через гараж.
- Положите вещей обратно на полки.
Разделение большой задачи на более мелкие и небольшие подзадачи помогает упростить рассмотрение большой задачи и управление ею. По мере того, как программы становятся более сложными, становится все более выгодным модулировать их таким образом.
Разделение пространства имен
Пространство имен - это область программы, в которой идентификаторы имеют значение.Как вы увидите ниже, когда вызывается функция Python, для этой функции создается новое пространство имен, которое отличается от всех других пространств имен, которые уже существуют.
Практический результат этого состоит в том, что переменные можно определять и использовать в функции Python, даже если они имеют то же имя, что и переменные, определенные в других функциях или в основной программе. В этих случаях не будет путаницы или вмешательства, потому что они хранятся в отдельных пространствах имен.
Это означает, что, когда вы пишете код внутри функции, вы можете использовать имена и идентификаторы переменных, не беспокоясь о том, использовались ли они где-то еще вне функции.Это помогает значительно минимизировать ошибки в коде.
Надеюсь, вы достаточно убедились в достоинствах функций и хотите их создать! Посмотрим как.
Вызов функций и определение
Обычный синтаксис для определения функции Python следующий:
def <имя_функции> ([<параметры>]):
<заявление (я)>
Компоненты определения поясняются в таблице ниже:
Компонент | Значение |
---|---|
по умолчанию | Ключевое слово, информирующее Python о том, что функция определяется |
<имя_функции> | Действительный идентификатор Python, который называет функцию |
<параметры> | Необязательный список параметров, разделенных запятыми, которые могут быть переданы функции |
: | Знаки препинания, обозначающие конец заголовка функции Python (имя и список параметров) |
<выписки> | Блок действительных операторов Python |
Последний элемент,
, называется телом функции.Тело - это блок операторов, который будет выполняться при вызове функции. Тело функции Python определяется отступом в соответствии с правилом off-side. Это то же самое, что и блоки кода, связанные со структурой управления, например, if
или while
.
Синтаксис для вызова функции Python следующий:
<имя_функции> ([<аргументы>])
<аргументы>
- значения, переданные в функцию.Они соответствуют <параметры>
в определении функции Python. Вы можете определить функцию, которая не принимает никаких аргументов, но круглые скобки по-прежнему необходимы. И определение функции, и вызов функции всегда должны включать круглые скобки, даже если они пусты.
Как обычно, вы начнете с небольшого примера, а затем добавите сложности. Помня об освященной веками математической традиции, вы вызовете свою первую функцию Python f ()
. Вот файл сценария foo.py
, который определяет и вызывает f ()
:
1def f ():
2 s = '- Внутри f ()'
3 отпечатка (ов)
4
5print ('Перед вызовом f ()')
6f ()
7print ('После вызова f ()')
Вот как работает этот код:
Строка 1 использует ключевое слово
def
, чтобы указать, что функция определяется. Выполнение оператораdef
просто создает определениеf ()
. Все следующие строки с отступом (строки 2–3) становятся частью телаf ()
и сохраняются как его определение, но еще не выполняются.Строка 4 - это небольшой пробел между определением функции и первой строкой основной программы. Хотя это и не является синтаксически необходимым, это приятно иметь. Чтобы узнать больше о пробелах вокруг определений функций Python верхнего уровня, прочтите статью Написание красивого кода Python с помощью PEP 8.
Строка 5 - это первый оператор без отступа, потому что он не является частью определения
f ()
. Это начало основной программы.Когда выполняется основная программа, этот оператор выполняется первым.Линия 6 - это звонок на
f ()
. Обратите внимание, что пустые круглые скобки всегда требуются как в определении функции, так и при ее вызове, даже если нет параметров или аргументов. Выполнение переходит кf ()
, и выполняются операторы в телеf ()
.Строка 7 - это следующая строка, которая выполняется после завершения тела
f ()
.Выполнение возвращается к этому операторуprint ()
.
Последовательность выполнения (или потока управления ) для foo.py
показана на следующей диаграмме:
Когда foo.py
запускается из командной строки Windows, результат будет следующим:
C: \ Users \ john \ Documents \ Python \ doc> python foo.py
Перед вызовом f ()
- Внутри f ()
После вызова f ()
Иногда вам может понадобиться определить пустую функцию, которая ничего не делает.Это называется заглушкой , которая обычно является временным заполнителем для функции Python, которая будет полностью реализована позже. Как блок в управляющей структуре не может быть пустым, так и тело функции не может быть пустым. Чтобы определить функцию-заглушку, используйте оператор pass
:
>>> def f ():
... проходить
...
>>> f ()
Как видно выше, вызов функции-заглушки синтаксически допустим, но ничего не делает.
Передан аргумент
До сих пор в этом руководстве функции, которые вы определили, не принимали никаких аргументов. Иногда это может быть полезно, и вы иногда будете писать такие функции. Однако чаще вам нужно передать данные в функцию , чтобы ее поведение могло изменяться от одного вызова к другому. Посмотрим, как это сделать.
Позиционные аргументы
Самый простой способ передать аргументы функции Python - использовать позиционных аргументов (также называемых обязательными аргументами ).В определении функции вы указываете в скобках список параметров, разделенных запятыми:
>>> >>> def f (кол-во, шт., Цена):
... print (f '{qty} {item} cost $ {price: .2f}')
...
При вызове функции указывается соответствующий список аргументов:
>>> >>> f (6, 'бананы', 1.74)
6 бананов стоят 1,74 доллара
Параметры ( кол-во
, предмет
и цена
) ведут себя как переменных , которые определены локально для функции.Когда функция вызывается, переданные аргументы ( 6
, 'бананы'
и 1.74
) привязывают к параметрам по порядку, как если бы путем присвоения переменной:
Параметр | Аргумент | |
---|---|---|
шт. | ← | 6 |
товар | ← | бананы |
цена | ← | 1.74 |
В некоторых текстах по программированию параметры, указанные в определении функции, называются формальными параметрами , а аргументы в вызове функции называются фактическими параметрами :
Хотя позиционные аргументы являются наиболее простым способом передачи данных в функцию, они также обеспечивают наименьшую гибкость. Во-первых, порядок аргументов в вызове должен соответствовать порядку параметров в определении.Конечно, ничто не мешает вам указывать позиционные аргументы не по порядку:
>>> >>> f ('бананы', 1.74, 6)
бананы 1.74 стоят $ 6.00
Функция может даже работать, как в приведенном выше примере, но маловероятно, что она даст правильные результаты. Это ответственность программиста, который определяет функцию, чтобы задокументировать, какими должны быть соответствующие аргументы , и ответственность пользователя функции - знать эту информацию и соблюдать ее.
С позиционными аргументами аргументы в вызове и параметры в определении должны согласовываться не только по порядку, но и по номеру и . По этой причине позиционные аргументы также называются обязательными аргументами. Вы не можете ничего пропустить при вызове функции:
>>> >>> # Слишком мало аргументов
>>> f (6, 'бананы')
Отслеживание (последний вызов последний):
Файл "", строка 1, в
f (6, 'бананы')
TypeError: f () отсутствует 1 обязательный позиционный аргумент: 'цена'
Вы также не можете указать лишние:
>>> >>> # Слишком много аргументов
>>> f (6, 'бананы', 1.74, кумкваты)
Отслеживание (последний вызов последний):
Файл "", строка 1, в
f (6, «бананы», 1,74, «кумкват»)
TypeError: f () принимает 3 позиционных аргумента, но было дано 4
Позиционные аргументы концептуально просты в использовании, но они не очень снисходительны. Вы должны указать такое же количество аргументов в вызове функции, как и параметры в определении, и в точно таком же порядке. В следующих разделах вы увидите некоторые приемы передачи аргументов, которые снимают эти ограничения.
Аргументы ключевого слова
При вызове функции можно указать аргументы в форме <ключевое слово> = <значение>
. В этом случае каждое <ключевое слово>
должно соответствовать параметру в определении функции Python. Например, ранее определенная функция f ()
может быть вызвана с аргументами ключевого слова следующим образом:
>>> f (кол-во = 6, товар = 'бананы', цена = 1,74)
6 бананов стоят 1,74 доллара
Ссылка на ключевое слово, не соответствующее ни одному из заявленных параметров, генерирует исключение:
>>> >>> f (qty = 6, item = 'bananas', cost = 1.74)
Отслеживание (последний вызов последний):
Файл "", строка 1, в
TypeError: f () получил неожиданный аргумент ключевого слова 'стоимость'
Использование аргументов ключевого слова снимает ограничение на порядок аргументов. Каждый аргумент ключевого слова явно обозначает конкретный параметр по имени, поэтому вы можете указать их в любом порядке, и Python все равно будет знать, какой аргумент соответствует какому параметру:
>>> >>> f (item = 'bananas', price = 1.74, qty = 6)
6 бананов стоят 1 доллар.74
Однако, как и в случае с позиционными аргументами, количество аргументов и параметров должно совпадать:
>>> >>> # Еще слишком мало аргументов
>>> f (кол-во = 6, элемент = 'бананы')
Отслеживание (последний вызов последний):
Файл "", строка 1, в
f (кол-во = 6, элемент = 'бананы')
TypeError: f () отсутствует 1 обязательный позиционный аргумент: 'цена'
Таким образом, аргументы ключевого слова допускают гибкость в порядке указания аргументов функции, но количество аргументов остается жестким.
Вы можете вызвать функцию, используя как позиционные, так и ключевые аргументы:
>>> >>> f (6, цена = 1.74, item = 'bananas')
6 бананов стоят 1,74 доллара
>>> f (6, 'бананы', цена = 1,74)
6 бананов стоят 1,74 доллара
Когда присутствуют как позиционные аргументы, так и аргументы ключевого слова, все позиционные аргументы должны идти первыми:
>>> >>> f (6, item = 'bananas', 1.74)
SyntaxError: позиционный аргумент следует за аргументом ключевого слова
После того, как вы указали аргумент ключевого слова, справа от него не может быть никаких позиционных аргументов.
Параметры по умолчанию
Если параметр, указанный в определении функции Python, имеет форму <имя> = <значение>
, тогда <значение>
становится значением по умолчанию для этого параметра. Параметры, определенные таким образом, называются параметрами по умолчанию или дополнительными параметрами . Пример определения функции с параметрами по умолчанию показан ниже:
>>> def f (qty = 6, item = 'bananas', price = 1.74):
... print (f '{qty} {item} cost $ {price :.2f} ')
...
Когда вызывается эта версия f ()
, любой аргумент, который не указан, принимает значение по умолчанию:
>>> f (4, 'яблоки', 2.24)
4 яблока стоят 2,24 доллара.
>>> f (4, 'яблоки')
4 яблока стоят 1,74 доллара
>>> f (4)
4 банана стоят 1,74 доллара
>>> f ()
6 бананов стоят 1,74 доллара
>>> f (item = 'кумкватов', кол-во = 9)
9 кумкватов стоят 1,74 доллара
>>> f (цена = 2,29)
6 бананов стоят 2,29 доллара
Итого:
- Позиционные аргументы должны соответствовать по порядку и номеру параметрам, объявленным в определении функции.
- Аргументы ключевого слова должны совпадать с объявленными параметрами по количеству, но они могут быть указаны в произвольном порядке.
- Параметры по умолчанию позволяют опускать некоторые аргументы при вызове функции.
Изменяемые значения параметров по умолчанию
Все может стать странным, если вы укажете значение параметра по умолчанию, которое является изменяемым объектом . Рассмотрим это определение функции Python:
>>> >>> def f (my_list = []):
... my_list.append ('###')
... вернуть my_list
...
f ()
принимает единственный параметр списка, добавляет строку '###'
в конец списка и возвращает результат:
>>> f (['foo', 'bar', 'baz'])
['foo', 'bar', 'baz', '###']
>>> f ([1, 2, 3, 4, 5])
[1, 2, 3, 4, 5, '###']
Значение по умолчанию для параметра my_list
- пустой список, поэтому, если f ()
вызывается без каких-либо аргументов, возвращаемое значение - это список с одним элементом '###'
:
Пока все имеет смысл.Итак, что вы ожидаете, если f ()
вызывается без каких-либо параметров второй и третий раз? Посмотрим:
>>> f ()
['###', '###']
>>> f ()
['###', '###', '###']
Ой! Вы могли ожидать, что каждый последующий вызов также будет возвращать одноэлементный список ['###']
, как и первый. Вместо этого возвращаемое значение продолжает расти. Что случилось?
В Python значения параметров по умолчанию определены только один раз , когда функция определена (то есть, когда выполняется инструкция def
).Значение по умолчанию не переопределяется каждый раз при вызове функции. Таким образом, каждый раз, когда вы вызываете f ()
без параметра, вы выполняете .append ()
в том же списке.
Вы можете продемонстрировать это с помощью id ()
:
>>> def f (my_list = []):
... печать (id (my_list))
... my_list.append ('###')
... вернуть my_list
...
>>> f ()
140095566958408
['###']
>>> f ()
140095566958408
['###', '###']
>>> f ()
140095566958408
['###', '###', '###']
Отображаемый идентификатор объекта подтверждает, что, когда для my_list
разрешено значение по умолчанию, значение будет одним и тем же объектом при каждом вызове.Поскольку списки изменяемы, каждый последующий вызов .append ()
заставляет список удлиняться. Это распространенная и довольно хорошо задокументированная ошибка, когда вы используете изменяемый объект в качестве значения параметра по умолчанию. Это потенциально приводит к путанице в поведении кода, и, вероятно, лучше этого избегать.
В качестве обходного пути рассмотрите возможность использования значения аргумента по умолчанию, которое сигнализирует , что аргумент не указан . Практически любое значение будет работать, но Нет
- обычный выбор. Когда значение дозорного указывает, что аргумент не задан, создайте новый пустой список внутри функции:
>>> def f (my_list = None):
... если my_list - None:
... my_list = []
... my_list.append ('###')
... вернуть my_list
...
>>> f ()
['###']
>>> f ()
['###']
>>> f ()
['###']
>>> f (['фу', 'бар', 'баз'])
['foo', 'bar', 'baz', '###']
>>> f ([1, 2, 3, 4, 5])
[1, 2, 3, 4, 5, '###']
Обратите внимание, как это гарантирует, что my_list
теперь действительно будет по умолчанию использовать пустой список всякий раз, когда f ()
вызывается без аргумента.
Передача по значению и передача по ссылке в Pascal
В разработке языков программирования есть две общие парадигмы для передачи аргумента функции:
- Передаваемое значение: Копия аргумента передается функции.
- Передача по ссылке: В функцию передается ссылка на аргумент.
Существуют и другие механизмы, но они по сути являются вариациями этих двух. В этом разделе вы сделаете небольшой отход от Python и кратко рассмотрите Pascal, язык программирования, который делает особенно четкое различие между этими двумя.
Примечание: Не волнуйтесь, если вы не знакомы с Паскалем! Концепции аналогичны концепциям Python, а показанные примеры сопровождаются достаточно подробным объяснением, чтобы вы могли составить общее представление.Как только вы увидели, как передача аргументов работает в Паскале, мы вернемся к Python, и вы увидите, как он сравнивается.
Вот что вам нужно знать о синтаксисе Паскаля:
- Процедуры: Процедура в Паскале похожа на функцию Python.
- Двоеточие равно: Этот оператор (
: =
) используется для присваивания в Паскале. Это аналог знака равенства (=
) в Python. -
Writeln ()
: Эта функция отображает данные на консоли, аналогично функции print () в Python.
Имея такую основу, вот первый пример Pascal:
1 // Пример Pascal # 1
2
3процедура f (fx: целое число);
4начать
5 Writeln ('Начать f (): fx =', fx);
6 FX: = 10;
7 Writeln ('Конец f (): fx =', fx);
8end;
9
10 // Основная программа
11вар
12 x: целое число;
13
14начало
15 х: = 5;
16 Writeln ('Перед f (): x =', x);
17 f (x);
18 Writeln ('После f (): x =', x);
19 конец.
Вот что происходит:
- Строка 12: Основная программа определяет целочисленную переменную
x
. - Строка 15: Первоначально
x
присваивается значение5
. - Строка 17: Затем он вызывает процедуру
f ()
, передаваяx
в качестве аргумента. - Строка 5: Внутри
f ()
инструкцияwriteln ()
показывает, что соответствующий параметрfx
изначально равен5
, переданное значение. - Строка 6:
fx
затем присваивается значение10
. - Строка 7: Это значение проверяется этим оператором
writeln ()
, выполняемым непосредственно перед выходом изf ()
. - Строка 18: Вернувшись в вызывающую среду основной программы, этот оператор
Writeln ()
показывает, что после возвратаf ()
x
все еще остается5
, как это было до вызова процедуры. .
Запуск этого кода дает следующий результат:
Перед f (): x = 5
Начать f (): fx = 5
Конец f (): fx = 10
После f (): x = 5
В этом примере x
— это , переданное по значению , поэтому f ()
получает только копию.Когда соответствующий параметр fx
изменяется, x
не изменяется.
Примечание: Если вы хотите увидеть это в действии, вы можете запустить код самостоятельно, используя онлайн-компилятор Pascal.
Просто выполните следующие действия:
- Скопируйте код из поля кода выше.
- Посетите онлайн-компилятор Паскаля.
- В поле кода слева замените любое существующее содержимое кодом, который вы скопировали на шаге 1.
- Щелкните Выполнить .
Вы должны увидеть тот же результат, что и выше.
Теперь сравните это со следующим примером:
1 // Пример Pascal # 2
2
3процедура f (var fx: integer);
4начать
5 Writeln ('Начать f (): fx =', fx);
6 FX: = 10;
7 Writeln ('Конец f (): fx =', fx);
8end;
9
10 // Основная программа
11вар
12 x: целое число;
13
14начало
15 х: = 5;
16 Writeln ('Перед f (): x =', x);
17 f (x);
18 Writeln ('После f (): x =', x);
19 конец.
Этот код идентичен первому примеру с одним изменением.Это наличие слова var
перед fx
в определении процедуры f ()
в строке 3. Это означает, что аргумент для f ()
— это , переданный по ссылке . Изменения, внесенные в соответствующий параметр fx
, также изменят аргумент в вызывающей среде.
Вывод этого кода такой же, как и раньше, за исключением последней строки:
Перед f (): x = 5
Начать f (): fx = 5
Конец f (): fx = 10
После f (): x = 10
Опять же, fx
присваивается значение 10
внутри f ()
, как и раньше.Но на этот раз, когда возвращается f ()
, x
в основной программе также было изменено.
Во многих языках программирования это, по сути, различие между передачей по значению и передачей по ссылке:
- Если переменная передается по значению, , тогда у функции есть копия для работы, но она не может изменить исходное значение в вызывающей среде.
- Если переменная передается по ссылке, , то любые изменения, которые функция вносит в соответствующий параметр, повлияют на значение в вызывающей среде.
Причина, почему происходит от того, что означает ссылка на этих языках. Значения переменных хранятся в памяти. В Паскале и подобных языках ссылка — это, по сути, адрес этой ячейки памяти, как показано ниже:
На диаграмме слева x
имеет память, выделенную в пространстве имен основной программы. Когда вызывается f ()
, x
— это , переданное значением , поэтому память для соответствующего параметра fx
выделяется в пространстве имен f ()
, и значение x
копируется туда. .Когда f ()
изменяет fx
, изменяется именно эта локальная копия. Значение x
в среде вызова остается неизменным.
На диаграмме справа x
— это , переданное по ссылке . Соответствующий параметр fx
указывает на фактический адрес в пространстве имен основной программы, где хранится значение x
. Когда f ()
изменяет fx
, он изменяет значение в этом месте, точно так же, как если бы основная программа изменяла саму x
.
Передача по значению и передача по ссылке в Python
Являются ли параметры в Python передачей по значению или по ссылке? Ответ таков: ни то, ни другое. Это потому, что ссылка в Python означает не совсем то же самое, что в Паскале.
Напомним, что в Python каждая часть данных представляет собой объект . Ссылка указывает на объект, а не на конкретную ячейку памяти. Это означает, что присваивание не интерпретируется в Python так же, как в Паскале. Рассмотрим следующую пару операторов на Паскале:
Они интерпретируются следующим образом:
- Переменная
x
ссылается на конкретную ячейку памяти. - Первый оператор помещает в это место значение
5
. - Следующий оператор перезаписывает
5
и помещает вместо него10
.
Напротив, в Python аналогичные операторы присваивания выглядят следующим образом:
Эти операторы присваивания имеют следующее значение:
- Первый оператор заставляет
x
указывать на объект, значение которого составляет5
. - Следующий оператор переназначает
x
как новую ссылку на другой объект, значение которого составляет10
. Другими словами, второе присвоение повторно привязываетx
к другому объекту со значением10
.
В Python, когда вы передаете аргумент функции, происходит аналогичное повторное связывание . Рассмотрим этот пример:
>>> 1 >>> def f (fx):
2 ... fx = 10
3 ...
4 >>> х = 5
5 >>> f (x)
6 >>> х
75
В основной программе оператор x = 5
в строке 5 создает ссылку с именем x
, привязанную к объекту, значение которого равно 5
.Затем в строке 7 вызывается f ()
с x
в качестве аргумента. При первом запуске f ()
создается новая ссылка с именем fx
, которая изначально указывает на тот же объект 5
, что и x
:
Однако, когда выполняется инструкция fx = 10
в строке 2, f ()
выполняет повторную привязку fx
к новому объекту, значение которого равно 10
. Две ссылки, x
и fx
, не связаны друг с другом на .Больше ничего из того, что делает f ()
, не повлияет на x
, и когда f ()
завершится, x
по-прежнему будет указывать на объект 5
, как это было до вызова функции:
Подтвердить все это можно с помощью id ()
. Вот слегка расширенная версия приведенного выше примера, которая отображает числовые идентификаторы задействованных объектов:
1 >>> def f (fx):
2 ... печать ('fx =', fx, '/ id (fx) =', id (fx))
3... fx = 10
4 ... печать ('fx =', fx, '/ id (fx) =', id (fx))
5 ...
6
7 >>> х = 5
8 >>> print ('x =', x, '/ id (x) =', id (x))
9x = 5 / id (x) = 1357
8
10
11 >>> f (x)
12fx = 5 / id (FX) = 13578
13fx = 10 / id (fx) = 13578
14
15 >>> печать ('x =', x, '/ id (x) =', id (x))
16x = 5 / id (x) = 13578
При первом запуске f ()
, fx
и x
оба указывают на один и тот же объект, чей id ()
равен 1357
8 .После того, как f ()
выполнит оператор fx = 10
в строке 3, fx
указывает на другой объект, чей id ()
равен 1357
8 . Связь с исходным объектом в вызывающей среде теряется.
Передача аргументов в Python — это своего рода гибрид между передачей по значению и передачей по ссылке. В функцию передается ссылка на объект, но ссылка передается по значению.
Примечание. Механизм передачи аргументов Python был назван передачей путем присвоения .Это связано с тем, что имена параметров привязаны к объектам при вводе функции в Python, а присвоение также является процессом привязки имени к объекту. Вы также можете увидеть термины «передача по объекту», «передача по ссылке на объект» или «передача по совместному использованию».
Ключевой вывод здесь заключается в том, что функция Python не может изменить значение аргумента, переназначив соответствующий параметр чему-то другому. Следующий пример демонстрирует это:
>>> >>> def f (x):
... x = 'foo'
...
>>> для i в (
... 40,
... dict (foo = 1, bar = 2),
... {1, 2, 3},
... 'бар',
... ['foo', 'bar', 'baz']):
... f (я)
... печать (я)
...
40
{'foo': 1, 'bar': 2}
{1, 2, 3}
бар
['фу', 'бар', 'баз']
Здесь объекты типа int
, dict
, set
, str
и list
передаются в f ()
в качестве аргументов. f ()
пытается назначить каждый объект строковому объекту 'foo'
, но, как вы можете видеть, вернувшись в вызывающую среду, все они не изменились.Как только f ()
выполнит присвоение x = 'foo'
, ссылка будет rebound , и соединение с исходным объектом будет потеряно.
Означает ли это, что функция Python вообще никогда не может изменять свои аргументы? На самом деле нет, это не так! Посмотрите, что здесь происходит:
>>> >>> def f (x):
... x [0] = '---'
...
>>> my_list = ['foo', 'bar', 'baz', 'qux']
>>> f (мой_лист)
>>> мой_лист
['---', 'bar', 'baz', 'qux']
В этом случае аргумент функции f ()
является списком.Когда вызывается f ()
, передается ссылка на my_list
. Вы уже видели, что f ()
не может переназначить my_list
оптом. Если бы x
было назначено чему-то другому, то оно было бы привязано к другому объекту, и соединение с my_list
было бы потеряно.
Однако f ()
может использовать ссылку для внесения изменений в my_list
. Здесь f ()
изменил первый элемент.Вы можете видеть, что после возврата из функции my_list
фактически был изменен в вызывающей среде. То же самое относится и к словарю:
>>> def f (x):
... x ['bar'] = 22
...
>>> my_dict = {'foo': 1, 'bar': 2, 'baz': 3}
>>> f (my_dict)
>>> my_dict
{'foo': 1, 'bar': 22, 'baz': 3}
Здесь f ()
использует x
в качестве ссылки для внесения изменений в my_dict
.Это изменение отражается в вызывающей среде после возврата f ()
.
Сводка по передаче аргументов
Передачу аргумента в Python можно резюмировать следующим образом. Передача неизменяемого объекта , такого как int
, str
, tuple
или frozenset
, в функцию Python действует как передача по значению. Функция не может изменять объект в вызывающей среде.
Передача изменяемого объекта , такого как список
, dict
или set
, действует в некоторой степени — но не совсем — как передача по ссылке.Функция не может переназначить объект оптом, но она может изменять элементы на месте внутри объекта, и эти изменения будут отражены в вызывающей среде.
Побочные эффекты
Итак, в Python вы можете изменить аргумент из функции, чтобы изменение отражалось в вызывающей среде. Но стоит ли вам это делать? Это пример того, что на жаргоне программирования называется побочным эффектом .
В более общем смысле говорят, что функция Python вызывает побочный эффект, если она каким-либо образом изменяет среду своего вызова.Изменение значения аргумента функции — лишь одна из возможностей.
Примечание: Вы, вероятно, знакомы с побочными эффектами из области здоровья человека, где этот термин обычно относится к непреднамеренным последствиям приема лекарств. Часто последствия нежелательны, например, рвота или седативный эффект. С другой стороны, побочные эффекты могут быть использованы намеренно. Например, некоторые лекарства вызывают стимуляцию аппетита, что может быть полезно, даже если это не является основным назначением лекарства.
Концепция аналогична в программировании. Если побочный эффект является хорошо задокументированной частью спецификации функции, и пользователь функции четко знает, когда и как вызывающая среда может быть изменена, тогда все в порядке. Но программист не всегда может должным образом документировать побочные эффекты или даже не подозревать о возникновении побочных эффектов.
Когда они скрыты или неожиданны, побочные эффекты могут привести к программным ошибкам, которые очень трудно отследить.Как правило, их лучше избегать.
Возврат
ЗаявлениеЧто тогда делать функции Python? В конце концов, во многих случаях, если функция не вызывает каких-либо изменений в вызывающей среде, тогда нет никакого смысла в ее вызове. Как функция должна влиять на вызывающего?
Ну, одна из возможностей — использовать значение , возвращаемое функцией . Оператор return
в функции Python служит двум целям:
- Он немедленно завершает функцию и передает управление выполнением обратно вызывающей стороне.
- Он предоставляет механизм, с помощью которого функция может передавать данные обратно вызывающей стороне.
Выход из функции
Внутри функции оператор return
вызывает немедленный выход из функции Python и передачу выполнения обратно вызывающей стороне:
>>> def f ():
... печать ('фу')
... печать ('полоса')
... возвращаться
...
>>> f ()
фу
бар
В этом примере оператор return
фактически лишний.Функция вернется к вызывающей стороне, когда она упадет с конца , то есть после выполнения последнего оператора тела функции. Таким образом, эта функция будет вести себя идентично без оператора return
.
Однако возвращает
инструкцию не обязательно в конце функции. Они могут появляться в любом месте тела функции и даже несколько раз. Рассмотрим этот пример:
1 >>> def f (x):
2 ... если x <0:
3... возвращаться
4 ... если x> 100:
5 ... вернуться
6 ... печать (x)
7 ...
8
9 >>> f (-3)
10 >>> f (105)
11 >>> f (64)
1264
Первые два вызова f ()
не вызывают никакого вывода, потому что выполняется инструкция return
и функция завершается преждевременно до того, как будет достигнут оператор print ()
в строке 6.
Такая парадигма может быть полезна для проверки ошибок в функции. Вы можете проверить несколько условий ошибки в начале функции, с возвратом операторов
, которые выручают, если есть проблема:
def f ():
если error_cond1:
возвращаться
если error_cond2:
возвращаться
если error_cond3:
возвращаться
<нормальная обработка>
Если ни одно из условий ошибки не обнаружено, функция может продолжить свою обычную обработку.
Возврат данных вызывающему абоненту
Помимо выхода из функции, оператор return
также используется для передачи данных обратно вызывающей стороне . Если за оператором возврата return
внутри функции Python следует выражение, то в вызывающей среде вызов функции оценивается как значение этого выражения:
1 >>> def f ():
2 ... вернуть 'foo'
3 ...
4
5 >>> s = f ()
6 >>> с
7'фу '
Здесь значение выражения f ()
в строке 5 равно 'foo'
, которое впоследствии присваивается переменной s
.
Функция может возвращать любой тип объекта . В Python это означает что угодно. В вызывающей среде вызов функции может использоваться синтаксически любым способом, который имеет смысл для типа объекта, который возвращает функция.
Например, в этом коде f ()
возвращает словарь. Тогда в вызывающей среде выражение f ()
представляет словарь, а f () ['baz']
является действительной ключевой ссылкой в этот словарь:
>>> def f ():
... return dict (foo = 1, bar = 2, baz = 3)
...
>>> f ()
{'foo': 1, 'bar': 2, 'baz': 3}
>>> f () ['баз']
3
В следующем примере f ()
возвращает строку, которую можно разрезать, как любую другую строку:
>>> def f ():
... вернуть 'foobar'
...
>>> f () [2: 4]
'ob'
Здесь f ()
возвращает список, который можно индексировать или разрезать:
>>> def f ():
... return ['foo', 'bar', 'baz', 'qux']
...
>>> f ()
['foo', 'bar', 'baz', 'qux']
>>> f () [2]
'баз'
>>> f () [:: - 1]
['qux', 'baz', 'bar', 'foo']
Если в инструкции return
указано несколько выражений, разделенных запятыми, они упаковываются и возвращаются как кортеж:
>>> def f ():
... вернуть 'foo', 'bar', 'baz', 'qux'
...
>>> тип (f ())
<класс 'кортеж'>
>>> t = f ()
>>> т
('foo', 'bar', 'baz', 'qux')
>>> a, b, c, d = f ()
>>> print (f'a = {a}, b = {b}, c = {c}, d = {d} ')
a = foo, b = bar, c = baz, d = qux
Если возвращаемое значение не указано, функция Python возвращает специальное значение Python Нет
:
>>> def f ():
... возвращаться
...
>>> print (f ())
Никто
То же самое происходит, если тело функции вообще не содержит оператора return
и функция отваливается от конца:
>>> def g ():
... проходить
...
>>> print (g ())
Никто
Напомним, что Нет.
является ложным при оценке в логическом контексте.
Поскольку функции, которые выходят через пустой оператор , возвращают
или выпадают из конца, возвращают Нет
, вызов такой функции может использоваться в логическом контексте:
>>> def f ():
... возвращаться
...
>>> def g ():
... проходить
...
>>> если f () или g ():
... печать ('да')
... еще:
... печать ('нет')
...
нет
Здесь вызовы как f ()
, так и g ()
являются ложными, поэтому f () или g ()
также являются, и выполняется предложение else
.
Возвращаясь к побочным эффектам
Предположим, вы хотите написать функцию, которая принимает целочисленный аргумент и удваивает его. То есть вы хотите передать в функцию целочисленную переменную, и когда функция вернется, значение переменной в вызывающей среде должно быть вдвое больше, чем было.В Паскале это можно сделать с помощью передачи по ссылке:
1процедура double (var x: integer);
2начало
3 х: = х * 2;
4end;
5
6вар
7 x: целое число;
8
9начало
10 х: = 5;
11 Writeln ('Перед вызовом процедуры:', x);
12 двойных (х);
13 Writeln ('После вызова процедуры:', x);
14 конец.
Выполнение этого кода дает следующий результат, который подтверждает, что double ()
действительно изменяет x
в вызывающей среде:
Перед вызовом процедуры: 5
После вызова процедуры: 10
В Python это не сработает.Как вы теперь знаете, целые числа Python неизменяемы, поэтому функция Python не может изменить целочисленный аргумент с помощью побочного эффекта:
>>> >>> def double (x):
... х * = 2
...
>>> х = 5
>>> двойной (х)
>>> х
5
Однако вы можете использовать возвращаемое значение для получения аналогичного эффекта. Просто напишите double ()
, чтобы он принимал целочисленный аргумент, удваивал его и возвращал удвоенное значение. Затем вызывающий абонент отвечает за присвоение, изменяющее исходное значение:
>>> def double (x):
... вернуть x * 2
...
>>> х = 5
>>> х = двойной (х)
>>> х
10
Возможно, это предпочтительнее модификации по побочным эффектам. Совершенно очевидно, что x
изменяется в вызывающей среде, потому что вызывающий делает это сам. В любом случае, это единственный вариант, потому что модификация с помощью побочного эффекта в этом случае не работает.
Тем не менее, даже в тех случаях, когда можно изменить аргумент с помощью побочного эффекта, использование возвращаемого значения может быть более ясным.Предположим, вы хотите удвоить каждый элемент в списке. Поскольку списки изменяемы, вы можете определить функцию Python, которая изменяет список на месте:
>>> >>> def double_list (x):
... я = 0
... пока я >> a = [1, 2, 3, 4, 5]
>>> double_list (а)
>>> а
[2, 4, 6, 8, 10]
В отличие от double ()
в предыдущем примере, double_list ()
фактически работает так, как задумано.Если в документации для функции четко указано, что содержимое аргумента списка изменено, это может быть разумной реализацией.
Однако вы также можете написать double_list ()
, чтобы передать желаемый список обратно по возвращаемому значению и позволить вызывающей стороне выполнить назначение, аналогично тому, как double ()
был переписан в предыдущем примере:
>>> def double_list (x):
... r = []
... для i в x:
... р.добавить (я * 2)
... вернуть г
...
>>> a = [1, 2, 3, 4, 5]
>>> а = двойной_лист (а)
>>> а
[2, 4, 6, 8, 10]
Оба подхода работают одинаково хорошо. Как это часто бывает, это вопрос стиля и личных предпочтений. Побочные эффекты не обязательно являются абсолютным злом, и они имеют свое место, но поскольку практически все может быть возвращено из функции, то же самое обычно можно достичь и с помощью возвращаемых значений.
Списки аргументов переменной длины
В некоторых случаях, когда вы определяете функцию, вы можете не знать заранее, сколько аргументов вы хотите, чтобы она принимала.Предположим, например, что вы хотите написать функцию Python, которая вычисляет среднее нескольких значений. Начать можно примерно так:
>>> >>> def avg (a, b, c):
... return (a + b + c) / 3
...
Все хорошо, если вы хотите усреднить три значения:
Однако, как вы уже видели, когда используются позиционные аргументы, количество переданных аргументов должно соответствовать количеству объявленных параметров. Тогда ясно, что с этой реализацией avg ()
для любого количества значений, кроме трех, не все в порядке:
>>> ср (1, 2, 3, 4)
Отслеживание (последний вызов последний):
Файл "", строка 1, в
средн. (1, 2, 3, 4)
TypeError: avg () принимает 3 позиционных аргумента, но было дано 4
Вы можете попробовать определить avg ()
с дополнительными параметрами:
>>> def avg (a, b = 0, c = 0, d = 0, e = 0):
....
....
....
...
Это позволяет указывать переменное количество аргументов. Следующие вызовы, по крайней мере, синтаксически верны:
в среднем (1)
ср (1, 2)
ср (1, 2, 3)
средн. (1, 2, 3, 4)
средн. (1, 2, 3, 4, 5)
Но при таком подходе все еще есть несколько проблем. Во-первых, он по-прежнему позволяет использовать до пяти аргументов, а не произвольное число. Что еще хуже, нет способа отличить указанные аргументы от аргументов, которым разрешено использовать по умолчанию.У функции нет способа узнать, сколько аргументов было фактически передано, поэтому она не знает, на что делить:
>>> >>> def avg (a, b = 0, c = 0, d = 0, e = 0):
... return (a + b + c + d + e) / # На что делить ???
...
Очевидно, и этого не пойдет.
Вы можете написать avg ()
, чтобы принимать единственный аргумент списка:
>>> def avg (a):
... всего = 0
... для v в:
... всего + = v
... return total / len (a)
...
>>> avg ([1, 2, 3])
2.0
>>> avg ([1, 2, 3, 4, 5])
3.0
По крайней мере, это работает. Он допускает произвольное количество значений и дает правильный результат. В качестве дополнительного бонуса это работает, когда аргумент также является кортежем:
>>> >>> t = (1, 2, 3, 4, 5)
>>> avg (t)
3.0
Недостатком является то, что дополнительный этап группировки значений в список или кортеж, вероятно, не является тем, чего ожидает пользователь функции, и это не очень элегантно.Всякий раз, когда вы находите код Python, который выглядит неэлегантно, вероятно, есть лучший вариант.
В данном случае действительно есть! Python предоставляет способ передать функции переменное количество аргументов с упаковкой и распаковкой кортежа аргументов с помощью оператора звездочки ( *
).
Упаковка кортежей аргументов
Если перед именем параметра в определении функции Python стоит звездочка ( *
), это указывает на упаковку кортежа аргументов . Все соответствующие аргументы в вызове функции упаковываются в кортеж, на который функция может ссылаться по заданному имени параметра.Вот пример:
>>> def f (* args):
... печать (аргументы)
... print (тип (аргументы), len (аргументы))
... для x в аргументах:
... печать (x)
...
>>> f (1, 2, 3)
(1, 2, 3)
<класс 'кортеж'> 3
1
2
3
>>> f ('foo', 'bar', 'baz', 'qux', 'quux')
('фу', 'бар', 'баз', 'qux', 'quux')
<класс 'кортеж'> 5
фу
бар
баз
qux
quux
В определении f ()
спецификация параметра * args
указывает на упаковку кортежа.При каждом вызове f ()
аргументы упаковываются в кортеж, на который функция может ссылаться по имени args
. Можно использовать любое имя, но args
выбирается настолько часто, что практически является стандартом.
Используя упаковку кортежей, вы можете очистить avg ()
следующим образом:
>>> def avg (* args):
... всего = 0
... для i в аргументах:
... всего + = я
... вернуть total / len (args)
...
>>> avg (1, 2, 3)
2.0
>>> avg (1, 2, 3, 4, 5)
3.0
Более того, вы можете привести его в порядок, заменив цикл на
на встроенную функцию Python sum ()
, которая суммирует числовые значения в любой итерации:
>>> def avg (* args):
... вернуть сумму (аргументы) / len (аргументы)
...
>>> avg (1, 2, 3)
2.0
>>> avg (1, 2, 3, 4, 5)
3.0
Теперь avg ()
написан лаконично и работает по назначению.
Тем не менее, в зависимости от того, как этот код будет использоваться, может быть, еще есть над чем поработать. Как написано, avg ()
выдаст исключение TypeError
, если какие-либо аргументы не являются числовыми:
>>> avg (1, 'foo', 3)
Отслеживание (последний вызов последний):
Файл "", строка 1, в
Файл "", строка 2, в среднем
TypeError: неподдерживаемые типы операндов для +: 'int' и 'str'
Чтобы быть максимально надежным, вы должны добавить код для проверки того, что аргументы имеют правильный тип.Позже в этой серии руководств вы узнаете, как перехватывать исключения, такие как TypeError
, и обрабатывать их соответствующим образом. Вы также можете проверить исключения Python: введение.
Распаковка кортежа аргументов
Аналогичная операция доступна на другой стороне уравнения в вызове функции Python. Когда аргументу в вызове функции предшествует звездочка ( *
), это означает, что аргумент представляет собой кортеж, который должен быть распакован, и передан в функцию как отдельные значения:
>>> def f (x, y, z):
... print (f'x = {x} ')
... print (f'y = {y} ')
... печать (f'z = {z} ')
...
>>> f (1, 2, 3)
х = 1
у = 2
г = 3
>>> t = ('фу', 'бар', 'баз')
>>> f (* t)
x = foo
y = бар
z = baz
В этом примере * t
в вызове функции указывает, что t
— это кортеж, который следует распаковать. Распакованные значения 'foo'
, 'bar'
и 'baz'
назначаются параметрам x
, y
и z
соответственно.
Хотя этот тип распаковки называется распаковкой кортежей , он работает не только с кортежами. Оператор звездочка ( *
) может применяться к любой итерации в вызове функции Python. Например, список или набор тоже можно распаковать:
>>> a = ['foo', 'bar', 'baz']
>>> тип (а)
<список классов>
>>> f (* а)
x = foo
y = бар
z = baz
>>> s = {1, 2, 3}
>>> тип (ы)
<класс 'набор'>
>>> f (* s)
х = 1
у = 2
г = 3
Вы даже можете использовать упаковку и распаковку кортежей одновременно:
>>> >>> def f (* args):
... print (тип (аргументы), аргументы)
...
>>> a = ['foo', 'bar', 'baz', 'qux']
>>> f (* а)
<класс 'кортеж'> ('foo', 'bar', 'baz', 'qux')
Здесь f (* a)
указывает, что список a
должен быть распакован, а элементы переданы в f ()
как отдельные значения. Спецификация параметра * args
заставляет значения упаковываться обратно в кортеж args
.
Упаковка словаря аргументов
Python имеет аналогичный оператор, двойную звездочку ( **
), который можно использовать с параметрами и аргументами функции Python для указания упаковки и распаковки словаря .Двойная звездочка ( **
) перед параметром в определении функции Python указывает на то, что соответствующие аргументы, которые, как ожидается, будут парами ключ = значение
, должны быть упакованы в словарь:
>>> def f (** kwargs):
... печать (kwargs)
... print (введите (kwargs))
... для ключа val в kwargs.items ():
... print (ключ, '->', val)
...
>>> f (foo = 1, bar = 2, baz = 3)
{'foo': 1, 'bar': 2, 'baz': 3}
<класс 'dict'>
foo -> 1
бар -> 2
баз -> 3
В этом случае аргументы foo = 1
, bar = 2
и baz = 3
упаковываются в словарь, на который функция может ссылаться по имени kwargs
.Опять же, можно использовать любое имя, но своеобразное kwargs
(сокращение от ключевого слова args ) почти стандартно. Вам не обязательно его придерживаться, но если вы это сделаете, то любой, кто знаком с соглашениями о кодировании Python, сразу поймет, что вы имеете в виду.
Распаковка словаря аргументов
Распаковка словаря аргументов аналогична распаковке кортежа аргументов. Когда двойная звездочка ( **
) предшествует аргументу в вызове функции Python, она указывает, что аргумент является словарем, который должен быть распакован, с полученными элементами, переданными в функцию как аргументы ключевого слова:
>>> def f (a, b, c):
... print (F'a = {a} ')
... печать (F'b = {b} ')
... печать (F'c = {c} ')
...
>>> d = {'a': 'foo', 'b': 25, 'c': 'qux'}
>>> е (** д)
a = foo
б = 25
c = qux
Элементы в словаре d
распаковываются и передаются в f ()
в качестве аргументов ключевого слова. Итак, f (** d)
эквивалентно f (a = 'foo', b = 25, c = 'qux')
:
>>> f (a = 'foo', b = 25, c = 'qux')
a = foo
б = 25
c = qux
На самом деле, проверьте это:
>>> >>> f (** dict (a = 'foo', b = 25, c = 'qux'))
a = foo
б = 25
c = qux
Здесь dict (a = 'foo', b = 25, c = 'qux')
создает словарь из указанных пар ключ / значение.Затем оператор двойной звездочки ( **
) распаковывает его и передает ключевые слова в f ()
.
Собираем все вместе
Подумайте о * args
как о списке позиционных аргументов переменной длины, а о ** kwargs
как о списке аргументов ключевого слова переменной длины.
Все три — стандартные позиционные параметры, * args
и ** kwargs
— могут использоваться в одном определении функции Python. Если да, то их следует указывать в таком порядке:
>>> def f (a, b, * args, ** kwargs):
... print (F'a = {a} ')
... печать (F'b = {b} ')
... print (F'args = {args} ')
... печать (F'kwargs = {kwargs} ')
...
>>> f (1, 2, 'foo', 'bar', 'baz', 'qux', x = 100, y = 200, z = 300)
а = 1
b = 2
args = ('foo', 'bar', 'baz', 'qux')
kwargs = {'x': 100, 'y': 200, 'z': 300}
Это обеспечивает столько гибкости, сколько вам может понадобиться в функциональном интерфейсе!
Множественные распаковки в вызове функции Python
Python версии 3.5 представил поддержку дополнительных обобщений распаковки, как указано в PEP 448.Одна вещь, которую позволяют эти улучшения, — это множественных распаковок в одном вызове функции Python:
>>> >>> def f (* args):
... для i в аргументах:
... печать (я)
...
>>> a = [1, 2, 3]
>>> t = (4, 5, 6)
>>> s = {7, 8, 9}
>>> f (* a, * t, * s)
1
2
3
4
5
6
8
9
7
Вы также можете указать несколько распаковок словарей в вызове функции Python:
>>> >>> def f (** kwargs):
... для k, v в kwargs.items ():
... print (k, '->', v)
...
>>> d1 = {'a': 1, 'b': 2}
>>> d2 = {'x': 3, 'y': 4}
>>> f (** d1, ** d2)
а -> 1
б -> 2
х -> 3
у -> 4
Примечание: Это расширение доступно только в Python версии 3.5 или новее. Если вы попробуете это в более ранней версии, то получите исключение SyntaxError
.
Кстати, операторы распаковки *
и **
применяются не только к переменным, как в примерах выше.Вы также можете использовать их с литералами, которые повторяются:
>>> def f (* args):
... для i в аргументах:
... печать (я)
...
>>> f (* [1, 2, 3], * [4, 5, 6])
1
2
3
4
5
6
>>> def f (** kwargs):
... для k, v в kwargs.items ():
... print (k, '->', v)
...
>>> f (** {'a': 1, 'b': 2}, ** {'x': 3, 'y': 4})
а -> 1
б -> 2
х -> 3
у -> 4
Здесь литеральные списки [1, 2, 3]
и [4, 5, 6]
указаны для распаковки кортежей, а буквальные словари {'a': 1, 'b': 2}
и {'x': 3, 'y': 4}
указаны для распаковки словаря.
Аргументы только для ключевых слов
Функцию Python в версии 3.x можно определить так, чтобы она принимала аргументов, содержащих только ключевые слова. . Это аргументы функции, которые должны быть указаны с помощью ключевого слова. Давайте рассмотрим ситуацию, в которой это может быть полезно.
Предположим, вы хотите написать функцию Python, которая принимает переменное количество строковых аргументов, объединяет их вместе, разделенные точкой ( "."
), и выводит их на консоль. Для начала подойдет что-то вроде этого:
>>> def concat (* args):
... print (f '-> {".". join (args)}')
...
>>> concat ('a', 'b', 'c')
-> a.b.c
>>> concat ('foo', 'bar', 'baz', 'qux').
-> foo.bar.baz.qux
В существующем виде выходной префикс жестко запрограммирован на строку '->'
. Что, если вы хотите изменить функцию, чтобы она также принимала это как аргумент, чтобы пользователь мог указать что-то еще? Это одна из возможностей:
>>> def concat (префикс, * args):
... print (f '{prefix} {".".join (аргументы)} ')
...
>>> concat ('//', 'a', 'b', 'c')
//a.b.c
>>> concat ('...', 'foo', 'bar', 'baz', 'qux')
... foo.bar.baz.qux
Это работает, как рекламируется, но в этом решении есть несколько нежелательных моментов:
Строка префикса
- Префикс
Вы могли подумать, что можете решить вторую проблему, указав параметр со значением по умолчанию, например, например:
>>> >>> def concat (prefix = '->', * args):
... print (f '{префикс} {".". join (args)}')
...
К сожалению, это работает не совсем правильно. Префикс
— это позиционный параметр , поэтому интерпретатор предполагает, что первый аргумент, указанный в вызове функции, является предполагаемым выходным префиксом.Это означает, что его нельзя пропустить и получить значение по умолчанию:
>>> concat ('a', 'b', 'c')
ab.c
Что если вы попытаетесь указать префикс
в качестве аргумента ключевого слова? Ну, вы не можете сначала указать:
>>> concat (prefix = '//', 'a', 'b', 'c')
Файл "", строка 1
SyntaxError: позиционный аргумент следует за аргументом ключевого слова
Как вы видели ранее, когда даны оба типа аргументов, все позиционные аргументы должны предшествовать любым аргументам ключевого слова.
Однако вы также не можете указать его последним:
>>> >>> concat ('a', 'b', 'c', prefix = '...')
Отслеживание (последний вызов последний):
Файл "", строка 1, в
TypeError: concat () получил несколько значений для аргумента prefix
Опять же, префикс
является позиционным параметром, поэтому ему назначается первый аргумент, указанный в вызове (в данном случае это 'a'
). Затем, когда он снова указывается в качестве аргумента ключевого слова в конце, Python думает, что он был назначен дважды.
Параметры только для ключевых слов помогают решить эту дилемму. В определении функции укажите * args
, чтобы указать переменное количество позиционных аргументов, а затем укажите префикс
после этого:
>>> def concat (* args, prefix = '->'):
... print (f '{префикс} {".". join (args)}')
...
В этом случае префикс
становится параметром только для ключевого слова. Его значение никогда не будет заполнено позиционным аргументом.Его можно указать только с помощью именованного аргумента ключевого слова:
>>> concat ('a', 'b', 'c', prefix = '...')
... a.b.c
Обратите внимание, что это возможно только в Python 3. В версии 2.x Python указание дополнительных параметров после параметра аргументов переменной * args
вызывает ошибку.
Аргументы, содержащие только ключевое слово, позволяют функции Python принимать переменное количество аргументов, за которыми следует одна или несколько дополнительных опций в качестве аргументов ключевого слова.Если вы хотите изменить concat ()
, чтобы можно было указать и символ-разделитель, вы можете добавить дополнительный аргумент, состоящий только из ключевых слов:
>>> def concat (* args, prefix = '->', sep = '.'):
... print (f '{префикс} {sep.join (args)}')
...
>>> concat ('a', 'b', 'c')
-> a.b.c
>>> concat ('a', 'b', 'c', prefix = '//')
//a.b.c
>>> concat ('a', 'b', 'c', prefix = '//', sep = '-')
// а-б-в
Если параметру, содержащему только ключевое слово, присвоено значение по умолчанию в определении функции (как в приведенном выше примере), а ключевое слово опущено при вызове функции, то предоставляется значение по умолчанию:
>>> >>> concat ('a', 'b', 'c')
-> а.до н.э
Если, с другой стороны, параметру не присвоено значение по умолчанию, то он становится обязательным, и если его не указать, возникает ошибка:
>>> >>> def concat (* аргументы, префикс):
... print (f '{префикс} {".". join (args)}')
...
>>> concat ('a', 'b', 'c', prefix = '...')
... a.b.c
>>> concat ('a', 'b', 'c')
Отслеживание (последний вызов последний):
Файл "", строка 1, в
TypeError: в concat () отсутствует 1 обязательный аргумент, содержащий только ключевое слово: 'prefix'
Что делать, если вы хотите определить функцию Python, которая принимает аргумент, состоящий только из ключевых слов, но не принимает переменное количество позиционных аргументов? Например, следующая функция выполняет указанную операцию с двумя числовыми аргументами:
>>> >>> def oper (x, y, op = '+'):
... если op == '+':
... вернуть x + y
... elif op == '-':
... вернуть x - y
... elif op == '/':
... вернуть x / y
... еще:
... return None
...
>>> опер (3, 4)
7
>>> опер (3, 4, '+')
7
>>> опер (3, 4, '/')
0,75
Если вы хотите сделать op
параметром только для ключевого слова, вы можете добавить посторонний параметр аргумента фиктивной переменной и просто игнорировать его:
>>> def oper (x, y, * ignore, op = '+'):
... если op == '+':
... вернуть x + y
... elif op == '-':
... вернуть x - y
... elif op == '/':
... вернуть x / y
... еще:
... return None
...
>>> oper (3, 4, op = '+')
7
>>> oper (3, 4, op = '/')
0,75
Проблема с этим решением заключается в том, что * ignore
поглощает любые посторонние позиционные аргументы, которые могут быть включены:
>>> oper (3, 4, «Мне здесь не место»)
7
>>> oper (3, 4, «Мне здесь не место», op = '/')
0.75
В этом примере не должно быть дополнительного аргумента (как объявляет сам аргумент). Вместо того, чтобы тихо добиться успеха, это действительно должно привести к ошибке. То, что это не так, в лучшем случае неопрятно. В худшем случае это может привести к вводящему в заблуждение результату:
Чтобы исправить это, версия 3 позволяет параметру аргумента переменной в определении функции Python быть просто звездочкой ( *
) с опущенным именем:
>>> def oper (x, y, *, op = '+'):
... если op == '+':
... вернуть x + y
... elif op == '-':
... вернуть x - y
... elif op == '/':
... вернуть x / y
... еще:
... return None
...
>>> oper (3, 4, op = '+')
7
>>> oper (3, 4, op = '/')
0,75
>>> oper (3, 4, «Мне здесь не место»)
Отслеживание (последний вызов последний):
Файл "", строка 1, в
TypeError: oper () принимает 2 позиционных аргумента, но было дано 3
>>> опер (3, 4, '+')
Отслеживание (последний вызов последний):
Файл "", строка 1, в
TypeError: oper () принимает 2 позиционных аргумента, но было дано 3
Параметр простого переменного аргумента *
указывает, что больше нет позиционных параметров.Это поведение генерирует соответствующие сообщения об ошибках, если указаны дополнительные. Он позволяет следовать параметрам, содержащим только ключевые слова.
Только позиционные аргументы
Начиная с Python 3.8, параметры функции также могут быть объявлены только позиционно , то есть соответствующие аргументы должны быть предоставлены позиционно и не могут быть указаны с помощью ключевого слова.
Чтобы обозначить некоторые параметры как позиционные, вы указываете косую черту (/
) в списке параметров определения функции.Все параметры слева от косой черты (/
) должны быть указаны позиционно. Например, в следующем определении функции x
и y
являются позиционными параметрами, но z
можно указать с помощью ключевого слова:
>>> # Это Python 3.8
>>> def f (x, y, /, z):
... print (f'x: {x} ')
... print (f'y: {y} ')
... print (f'z: {z} ')
...
Это означает, что действительны следующие вызовы:
>>> >>> f (1, 2, 3)
х: 1
г: 2
z: 3
>>> f (1, 2, z = 3)
х: 1
г: 2
z: 3
Однако следующий вызов f ()
недействителен:
>>> f (x = 1, y = 2, z = 3)
Отслеживание (последний вызов последний):
Файл "", строка 1, в
TypeError: f () получила некоторые позиционные аргументы, переданные как аргументы ключевого слова:
'х, у'
Позиционные указатели и указатели только для ключевых слов могут использоваться в одном и том же определении функции:
>>> >>> # Это Python 3.8
>>> def f (x, y, /, z, w, *, a, b):
... print (x, y, z, w, a, b)
...
>>> f (1, 2, z = 3, w = 4, a = 5, b = 6)
1 2 3 4 5 6
>>> f (1, 2, 3, w = 4, a = 5, b = 6)
1 2 3 4 5 6
В этом примере:
-
x
иy
являются только позиционными. -
a
иb
— только ключевые слова. -
z
иw
можно указать позиционно или по ключевому слову.
Для получения дополнительной информации о позиционных параметрах см. Основные моменты выпуска Python 3.8.
Строки документации
Когда первая инструкция в теле функции Python является строковым литералом, она называется строкой документации функции . Строка документации используется для предоставления документации для функции. Он может содержать назначение функции, аргументы, которые она принимает, информацию о возвращаемых значениях или любую другую информацию, которая, по вашему мнению, будет полезной.
Ниже приведен пример определения функции со строкой документации:
>>> >>> def avg (* args):
... "" "Возвращает среднее значение списка числовых значений." ""
... вернуть сумму (аргументы) / len (аргументы)
...
Технически, строки документации могут использовать любой из механизмов цитирования Python, но рекомендуемое соглашение — использовать тройные кавычки, использовать символы двойных кавычек ( "" "
), как показано выше. котировки закрытия должны находиться на той же строке, что и котировки открытия.
Многострочные строки документации используются для более объемной документации.Многострочная строка документации должна состоять из итоговой строки, за которой следует пустая строка, за которой следует более подробное описание. Котировки закрытия должны быть на отдельной строке:
>>> >>> def foo (bar = 0, baz = 1):
... "" "Выполните преобразование foo.
...
... Аргументы ключевого слова:
... bar - величина по оси бара (по умолчанию = 0)
... baz - величина по оси baz (по умолчанию = 1)
... "" "
...
...
Форматирование строки документации и семантические соглашения подробно описаны в PEP 257.
Когда определена строка документации, интерпретатор Python назначает ее специальному атрибуту функции с именем __doc__
. Этот атрибут является одним из набора специализированных идентификаторов в Python, которые иногда называют магическими атрибутами или магическими методами , потому что они предоставляют специальные языковые функции.
Примечание: Эти атрибуты также упоминаются с помощью атрибутов dunder с красочным псевдонимом и методов dunder. Слово dunder объединяет d из double и под из символа подчеркивания ( _
).В будущих уроках этой серии вы встретите еще много неприятных атрибутов и методов.
Вы можете получить доступ к строке документации функции с помощью выражения
. Строки документации для приведенных выше примеров могут отображаться следующим образом:
>>> печать (ср .__ doc__)
Возвращает среднее значение списка числовых значений.
>>> печать (foo .__ doc__)
Выполните преобразование foo.
Аргументы ключевого слова:
bar - величина по оси бара (по умолчанию = 0)
baz - величина по оси baz (по умолчанию = 1)
В интерактивном интерпретаторе Python вы можете ввести help (
, чтобы отобразить строку документации для
:
>>> справка (в среднем)
Справка по функции avg в модуле __main__:
avg (* аргументы)
Возвращает среднее значение списка числовых значений.>>> help (foo)
Справка по функции foo в модуле __main__:
foo (bar = 0, baz = 1)
Выполните преобразование foo.
Аргументы ключевого слова:
bar - величина по оси бара (по умолчанию = 0)
baz - величина по оси baz (по умолчанию = 1)
Считается хорошей практикой кодирования указывать строку документации для каждой определяемой вами функции Python. Дополнительные сведения о строках документации см. В документе «Документирование кода Python: полное руководство».
Аннотации функций Python
Начиная с версии 3.0, Python предоставляет дополнительную возможность для документирования функции, которая называется аннотацией функции . Аннотации позволяют прикреплять метаданные к параметрам функции и возвращаемому значению.
Чтобы добавить аннотацию к параметру функции Python, вставьте двоеточие (:
), за которым следует любое выражение после имени параметра в определении функции. Чтобы добавить аннотацию к возвращаемому значению, добавьте символы ->
и любое выражение между закрывающей круглой скобкой списка параметров и двоеточием, завершающим заголовок функции.Вот пример:
>>> def f (a: '', b: '') -> '':
... проходить
...
Аннотация для параметра a
— это строка ''
, для b
строка ''
, а для значения, возвращаемого функцией, строка '
.
Интерпретатор Python создает словарь из аннотаций и назначает их другому специальному атрибуту dunder функции с именем __annotations__
.Аннотации для функции Python f ()
, показанные выше, могут отображаться следующим образом:
>>> f .__ annotations__
{'a': '', 'b': '', 'return': ''}
Ключи для параметров — это имена параметров. Ключом для возвращаемого значения является строка 'return'
:
>>> f .__ annotations __ ['a']
""
>>> f .__ аннотации __ ['b']
''
>>> е.__annotations __ ['return']
''
Обратите внимание, что аннотации не ограничиваются строковыми значениями. Это может быть любое выражение или объект. Например, вы можете комментировать объекты типа:
>>> >>> def f (a: int, b: str) -> float:
... print (a, b)
... вернуть (3.5)
...
>>> f (1, 'фу')
1 фу
3.5
>>> f .__ annotations__
{'a': <класс 'int'>, 'b': <класс 'str'>, 'return': <класс 'float'>}
Аннотация может быть даже составным объектом, например списком или словарем, поэтому к параметрам и возвращаемому значению можно прикрепить несколько элементов метаданных:
>>> >>> def area (
... р: {
... 'desc': 'радиус круга',
... 'тип': поплавок
...}) -> \
... {
... 'desc': 'площадь круга',
... 'тип': поплавок
...}:
... return 3.14159 * (r ** 2)
...
>>> площадь (2,5)
19,6349375
>>> area .__ annotations__
{'r': {'desc': 'радиус круга', 'type': },
'return': {'desc': 'область круга', 'type': }}
>>> area .__ annotations __ ['r'] ['desc']
'радиус круга'
>>> площадь.__annotations __ ['return'] ['type']
<класс 'float'>
В приведенном выше примере аннотация прикреплена к параметру r
и к возвращаемому значению. Каждая аннотация представляет собой словарь, содержащий описание строки и объект типа.
Если вы хотите присвоить значение по умолчанию параметру, имеющему аннотацию, то значение по умолчанию идет после аннотации:
>>> >>> def f (a: int = 12, b: str = 'baz') -> float:
... print (a, b)
... вернуть (3.5)
...
>>> f .__ annotations__
{'a': <класс 'int'>, 'b': <класс 'str'>, 'return': <класс 'float'>}
>>> f ()
12 баз
3.5
Что делают аннотации? Откровенно говоря, они почти ничего не делают. Они просто вроде как там. Давайте снова посмотрим на один из приведенных выше примеров, но с небольшими изменениями:
>>> >>> def f (a: int, b: str) -> float:
... print (a, b)
... вернуть 1, 2, 3
...
>>> f ('фу', 2.5)
foo 2.5
(1, 2, 3)
Что здесь происходит? Аннотации для f ()
указывают, что первый аргумент — int
, второй аргумент — str
, а возвращаемое значение — float
. Но последующий вызов f ()
нарушает все правила! Аргументы: str
и float
соответственно, а возвращаемое значение — кортеж. И все же переводчик позволяет всему этому скользить без каких-либо жалоб.
Аннотации не накладывают никаких семантических ограничений на код вообще. Это просто биты метаданных, прикрепленные к параметрам функции Python и возвращаемому значению. Python послушно прячет их в словаре, присваивает словарю атрибут dunder функции __annotations__
, и все. Аннотации являются необязательными и вообще не влияют на выполнение функций Python.
Процитирую Амала в «» Амаль и ночные посетители : «Какая тогда польза от этого?»
Для начала, аннотации составляют хорошую документацию .Вы, конечно, можете указать ту же информацию в строке документации, но размещение ее непосредственно в определении функции добавляет ясности. Типы аргументов и возвращаемое значение очевидны с первого взгляда для такого заголовка функции:
def f (a: int, b: str) -> float:
Конечно, интерпретатор не требует соблюдения указанных типов, но, по крайней мере, они понятны для тех, кто читает определение функции.
Deep Dive: принудительная проверка типов
Если бы вы были склонны, вы могли бы добавить код для принудительного применения типов, указанных в аннотациях к функциям.Вот функция, которая проверяет фактический тип каждого аргумента на соответствие тому, что указано в аннотации для соответствующего параметра. Он отображает
>>>Истинно
, если они совпадают, иЛожь
, если нет:>>> def f (a: int, b: str, c: float): ... импорт осмотреть ... args = inspect.getfullargspec (f) .args ... аннотации = inspect.getfullargspec (f) .annotations ... для x в аргументах: ... print (x, '->', ... 'arg is', type (locals () [x]), ',', ... 'annotation is', annotations [x], ... '/', (type (locals () [x])) is annotations [x]) ... >>> f (1, 'foo', 3.3) a -> arg - это
, аннотация - это / True b -> arg - , аннотация - / True c -> arg - , аннотация - / True >>> f ('фу', 4.3, 9) a -> arg - , аннотация - / False b -> arg - , аннотация - / False c -> arg - , аннотация - / False >>> f (1, 'фу', 'бар') a -> arg - это , аннотация - это / True b -> arg - , аннотация - / True c -> arg - , аннотация - / False (Модуль
inspect
содержит функции, которые получают полезную информацию о живых объектах — в данном случае функцияf ()
.)Функция, определенная как указанная выше, при желании может предпринять какие-то корректирующие действия, когда обнаружит, что переданные аргументы не соответствуют типам, указанным в аннотациях.
Фактически, схема использования аннотаций для выполнения проверки статического типа в Python описана в PEP 484. Доступна бесплатная программа проверки статического типа для Python под названием mypy, основанная на спецификации PEP 484.
Есть еще одно преимущество использования аннотаций.Стандартизованный формат, в котором аннотационная информация хранится в атрибуте __annotations__
, позволяет анализировать сигнатуры функций автоматическими инструментами.
В аннотациях нет ничего особенного. Вы даже можете определить свой собственный без специального синтаксиса, предоставляемого Python. Вот определение функции Python с аннотациями объекта типа, прикрепленными к параметрам и возвращаемому значению:
>>> >>> def f (a: int, b: str) -> float:
... возвращаться
...
>>> f .__ annotations__
{'a': <класс 'int'>, 'b': <класс 'str'>, 'return': <класс 'float'>}
По сути, это та же функция со словарем __annotations__
, созданным вручную:
>>> def f (a, b):
... возвращаться
...
>>> f .__ annotations__ = {'a': int, 'b': str, 'return': float}
>>> f .__ annotations__
{'a': <класс 'int'>, 'b': <класс 'str'>, 'return': <класс 'float'>}
Эффект идентичен в обоих случаях, но первый на первый взгляд визуально более привлекателен и удобочитаем.
Фактически, атрибут __annotations__
существенно не отличается от большинства других атрибутов функции. Например, его можно динамически изменять. Вы можете использовать атрибут возвращаемого значения, чтобы подсчитать, сколько раз функция выполняется:
>>> def f () -> 0:
... f .__ аннотации __ ['return'] + = 1
... print (f "f () был выполнен {f .__ annotations __ ['return']} время (с)")
...
>>> f ()
f () выполнено 1 раз (а)
>>> f ()
f () было выполнено 2 раза (а)
>>> f ()
f () было выполнено 3 раза (а)
Аннотации функций Python — это не что иное, как словари метаданных.Просто так получилось, что вы можете создать их с помощью удобного синтаксиса, поддерживаемого интерпретатором. Это все, что вы хотите из них сделать.
Заключение
По мере роста приложений становится все более важным модулировать код, разбивая его на более мелкие функции управляемого размера. Надеюсь, теперь у вас есть все необходимые инструменты для этого.
Вы узнали:
- Как создать пользовательскую функцию в Python
- Несколько разных способов передать аргументов функции
- Как можно вернуть данные из функции ее вызывающему
- Как добавить документацию к функциям с строками документации и аннотациями
Следующими в этой серии являются два руководства, которые охватывают поиск и сопоставление с образцом .Вы получите подробный обзор модуля Python под названием re , который содержит функции для поиска и сопоставления с использованием универсального синтаксиса шаблонов, называемого регулярным выражением .
Смотреть сейчас Это руководство содержит соответствующий видеокурс, созданный командой Real Python. Просмотрите его вместе с письменным руководством, чтобы углубить свое понимание: Определение и вызов функций Python
(Учебное пособие) Функции Python — DataCamp
Функции являются неотъемлемой частью языка программирования Python: вы, возможно, уже сталкивались и использовали некоторые из множества фантастических функций, встроенных в язык Python или поставляемых с его библиотечной экосистемой.Однако, как специалисту по данным, вам постоянно нужно будет писать свои собственные функции для решения проблем, которые ставят перед вами ваши данные.
Вот почему этот пост познакомит вас с функциями в Python. Вы рассмотрите следующие темы:
(Чтобы попрактиковаться дальше, попробуйте курс DataCamp по Python Data Science Toolbox (часть 1)!)
Функции в Python
Вы используете функции в программировании, чтобы связать набор инструкций, которые вы хотите использовать многократно или которые из-за своей сложности лучше изолированы в подпрограмме и вызываются при необходимости.Это означает, что функция — это фрагмент кода, написанный для выполнения определенной задачи. Для выполнения этой конкретной задачи функции может потребоваться или не потребоваться несколько входов. Когда задача выполняется, функция может или не может возвращать одно или несколько значений.
В Python есть три типа функций:
- Встроенные функции, такие как
help ()
для запроса помощи,min ()
для получения минимального значения,print ()
для печати объекта на терминале,… Вы можете найти обзор с больше этих функций здесь. - Пользовательские функции (UDF), которые представляют собой функции, которые пользователи создают, чтобы помочь им; И
- Анонимные функции, которые также называются лямбда-функциями, потому что они не объявлены со стандартным ключевым словом
def
.
Функции и методы
Метод относится к функции, которая является частью класса. Вы получаете доступ к нему с помощью экземпляра или объекта класса. У функции нет этого ограничения: она просто относится к отдельной функции.Это означает, что все методы являются функциями, но не все функции являются методами.
Рассмотрим этот пример, где вы сначала определяете функцию plus ()
, а затем класс суммирования
с методом sum ()
:
eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6IiMgRGVmaW5lIGEgZnVuY3Rpb24gYHBsdXMoKWBcbmRlZiBwbHVzKGEsYik6XG4gIHJldHVybiBhICsgYlxuICBcbiMgQ3JlYXRlIGEgYFN1bW1hdGlvbmAgY2xhc3NcbmNsYXNzIFN1bW1hdGlvbihvYmplY3QpOlxuICBkZWYgc3VtKHNlbGYsIGEsIGIpOlxuICAgIHNlbGYuY29udGVudHMgPSBhICsgYlxuICAgIHJldHVybiBzZWxmLmNvbnRlbnRzICJ9
Если теперь вы хотите вызвать метод sum ()
, который является частью класса Sumutation
, вам сначала нужно определить экземпляр или объект этого класса.Итак, давайте определим такой объект:
eyJsYW5ndWFnZSI6InB5dGhvbiIsInByZV9leGVyY2lzZV9jb2RlIjoiZGVmIHBsdXMoYSxiKTpcbiAgcmV0dXJuIGEgKyBiXG4gIFxuY2xhc3MgU3VtbWF0aW9uKG9iamVjdCk6XG4gIGRlZiBzdW0oc2VsZiwgYSwgYik6XG4gICAgc2VsZi5jb250ZW50cyA9IGEgKyBiXG4gICAgcmV0dXJuIHNlbGYuY29udGVudHMgIiwic2FtcGxlIjoiIyBJbnN0YW50aWF0ZSBgU3VtbWF0aW9uYCBjbGFzcyB0byBjYWxsIGBzdW0oKWBcbnN1bUluc3RhbmNlID0gU3VtbWF0aW9uKClcbnN1bUluc3RhbmNlLnN1bSgxLDIpIn0 =
Помните, что в этом экземпляре нет необходимости, если вы хотите вызвать функцию plus ()
! Вы сможете без проблем выполнить plus (1,2)
в фрагменте кода DataCamp Light!
Параметры и аргументы
Параметры — это имена, используемые при определении функции или метода, в которые будут отображаться аргументы.Другими словами, аргументы — это вещи, которые передаются при вызове любой функции или метода, в то время как код функции или метода ссылается на аргументы по их именам параметров.
Рассмотрим следующий пример и вернемся к приведенному выше фрагменту DataCamp Light: вы передаете два аргумента методу sum ()
класса Sumutation
, даже если вы ранее определили три параметра , а именно, self
, a
и b
.
Что случилось с self
?
Первым аргументом каждого метода класса всегда является ссылка на текущий экземпляр класса, которым в данном случае является суммирование
. По соглашению этот аргумент называется self
.
Все это означает, что в данном случае вы не передаете ссылку на self
, потому что self
— это имя параметра для неявно переданного аргумента, который ссылается на экземпляр, через который вызывается метод.Он неявно вставляется в список аргументов.
Как определить функцию: определяемые пользователем функции (UDF)
Четыре шага для определения функции в Python следующие:
- Используйте ключевое слово
def
, чтобы объявить функцию, а затем укажите имя функции. - Добавьте параметры к функции: они должны быть в скобках функции. Завершите строку двоеточием.
- Добавьте операторы, которые должны выполняться функциями.
- Завершите функцию оператором return, если функция должна что-то выводить. Без оператора return ваша функция вернет объект
None
.
eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6ImRlZiBoZWxsbygpOlxuICBwcmludChcIkhlbGxvIFdvcmxkXCIpIFxuICByInZXR1 = 9cm4g
Конечно, ваши функции будут усложняться по мере вашего продвижения: вы можете добавить к нему циклы for, управление потоком и т. Д., Чтобы сделать его более детализированным:
def привет ():
name = str (input ("Введите свое имя:"))
если имя:
print ("Привет" + str (имя))
еще:
print ("Привет, мир")
возвращаться
привет ()
В приведенной выше функции вы просите пользователя указать имя.Если имя не указано, функция распечатает «Hello World». В противном случае пользователь получит персональный ответ «Привет».
Помните также, что вы можете определить один или несколько параметров функции для своей UDF. Вы узнаете об этом больше, когда займетесь разделом «Аргументы функций». Кроме того, вы можете или не можете вернуть одно или несколько значений в результате вашей функции.
Возврат
Заявление Обратите внимание, что когда вы что-то печатаете в своем UDF hello ()
, вам не нужно его возвращать.Не будет никакой разницы между приведенной выше функцией и этой:
eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6ImRlZiBoZWxsb19ub3JldHVybigpOlxuICBwcmludChcIkhlbGxvIFdvcmxkXCIpICJ9
Однако, если вы хотите продолжить работу с результатом вашей функции и опробовать некоторые операции с ним, вам нужно будет использовать оператор return
, чтобы фактически вернуть значение, такое как String, целое число,…. Рассмотрим следующий сценарий, где hello ()
возвращает строку "hello"
, а функция hello_noreturn ()
возвращает None
:
eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6ImRlZiBoZWxsbygpOlxuICBwcmludChcIkhlbGxvIFdvcmxkXCIpIFxuICByZXR1cm4oXCJoZWxsb1wiKVxuXG5kZWYgaGVsbG9fbm9yZXR1cm4oKTpcbiAgcHJpbnQoXCJIZWxsbyBXb3JsZFwiKVxuICBcbiMgTXVsdGlwbHkgdGhlIG91dHB1dCBvZiBgaGVsbG8oKWAgd2l0aCAyIFxuaGVsbG8oKSAqIDJcblxuIyAoVHJ5IHRvKSBtdWx0aXBseSB0aGUgb3V0cHV0IG9mIGBoZWxsb19ub3JldHVybigpYCB3aXRoIDIgXG5oZWxsb19ub3JldHVybigpICogMiJ9
Вторая функция выдает ошибку, потому что вы не можете выполнять какие-либо операции с Нет
.Вы получите ошибку TypeError
, которая говорит, что вы не можете выполнить операцию умножения для NoneType
( None
, который является результатом hello_noreturn ()
) и int
( 2
).
Подсказка Функции немедленно завершают работу, когда сталкиваются с оператором return
, даже если это означает, что они не возвращают никакого значения:
eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6ImRlZiBydW4oKTpcbiAgZm9yIHggaW4gcmFuZ2UoMTApOlxuICAgICBpZiB4ID09IDI6XG4gICAgICAgcmV0dXJuXG4gIHByaW50KFwiUnVuIVwiKVxuICBcbnJ1bigpIn0 =
Еще одна вещь, о которой стоит упомянуть при работе с оператором return
, — это то, что вы можете использовать его для возврата нескольких значений.Для этого вы используете кортежи.
Помните , что эта структура данных очень похожа на структуру списка: она может содержать несколько значений. Однако кортежи неизменяемы, а это значит, что вы не можете изменять какие-либо суммы, которые в них хранятся! Вы строите его с помощью двойных скобок ()
. Вы можете распаковать кортежи в несколько переменных с помощью запятой и оператора присваивания.
Посмотрите следующий пример, чтобы понять, как ваша функция может возвращать несколько значений:
eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6IiMgRGVmaW5lIGBwbHVzKClgXG5kZWYgcGx1cyhhLGIpOlxuICBzdW0gPSBhICsgYlxuICByZXR1cm4gKHN1bSwgYSlcblxuIyBDYWxsIGBwbHVzKClgIGFuZCB1bnBhY2sgdmFyaWFibGVzIFxuc3VtLCBhID0gcGx1cygzLDQpXG5cbiMgUHJpbnQgYHN1bSgpYFxucHJpbnQoc3VtKSJ9
Обратите внимание, , что return
statement return sum, a
будет иметь тот же результат, что и return (sum, a)
: первый фактически упаковывает sum
и a
в кортеж под капотом!
Как вызвать функцию
В предыдущих разделах вы уже видели множество примеров того, как вы можете вызвать функцию.Вызов функции означает, что вы выполняете функцию, которую вы определили — либо непосредственно из приглашения Python, либо через другую функцию (как вы увидите в разделе «Вложенные функции»).
Вызовите новую функцию hello ()
, просто выполнив hello ()
, как в фрагменте DataCamp Light ниже:
eyJsYW5ndWFnZSI6InB5dGhvbiIsInByZV9leGVyY2lzZV9jb2RlIjoiZGVmIGhlbGxvKCk6XG4gIHByaW50KFwiSGVHsbG8gV29XBGRCIik
Как добавить строки документации к функции Python
Еще один важный аспект написания функций на Python: строки документации.Строки документации описывают, что делает ваша функция, например выполняемые вычисления или возвращаемые значения. Эти описания служат в качестве документации для вашей функции, так что любой, кто читает строку документации вашей функции, понимает, что делает ваша функция, без необходимости прослеживать весь код в определении функции.
Строки документации функции помещаются в строку сразу после заголовка функции и заключаются в тройные кавычки. Подходящей строкой документации для функции hello ()
является «Печать« Hello World »».
def привет ():
"" "Печать" Hello World ".
Возврат:
Никто
"" "
print ("Привет, мир")
возврат
Обратите внимание, , что строки документации могут быть более длинными, чем та, которая приведена здесь в качестве примера. Если вы хотите изучить строки документации более подробно, вам лучше всего проверить некоторые репозитории Github библиотек Python, такие как scikit-learn или pandas, где вы найдете множество примеров!
Аргументы функций в Python
Ранее вы узнали о разнице между параметрами и аргументами.Короче говоря, аргументы — это вещи, которые передаются при вызове любой функции или метода, в то время как код функции или метода ссылается на аргументы по их именам параметров. UDF-функции Python могут принимать четыре типа аргументов:
- Аргументы по умолчанию
- Обязательные аргументы
- Аргументы ключевого слова
- Переменное количество аргументов
Аргументы по умолчанию
Аргументы по умолчанию — это те, которые принимают значение по умолчанию, если во время вызова функции значение аргумента не передается.Вы можете назначить это значение по умолчанию с помощью оператора присваивания =
, как в следующем примере:
eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6IiMgRGVmaW5lIGBwbHVzKClgIGZ1bmN0aW9uXG5kZWYgcGx1cyhhLGIgPSAyKTpcbiAgcmV0dXJuIGEgKyBiXG4gIFxuIyBDYWxsIGBwbHVzKClgIHdpdGggb25seSBgYWAgcGFyYW1ldGVyXG5wbHVzKGE9MSlcblxuIyBDYWxsIGBwbHVzKClgIHdpdGggYGFgIGFuZCBgYmAgcGFyYW1ldGVyc1xucGx1cyhhPTEsIGI9MykifQ ==
Обязательные аргументы
Как видно из названия, обязательные аргументы UDF — это те, которые должны быть там.Эти аргументы необходимо передавать во время вызова функции и в точном порядке, как в следующем примере:
eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6IiMgRGVmaW5lIGBwbHVzKClgIHdpdGggcmVxdWlyZWQgYXJndW1lbnRZSI6InB5dGhvbiIsInNhbXBsZSI6IiMgRGVmaW5lIGBwbHVzKClgIHdpdGggcmVxdWlyZWQgYXJndW1lbnRzXG5kZcy4yhlxRXGx1lbnRzXG5kZcy4yhxRXMXXXXXXXXXXXXXXXXXXXXXXXXXXXMXXXXXX
Вам нужны аргументы, которые сопоставляются с a
, а также с параметрами b
для вызова функции без получения каких-либо ошибок. Если вы поменяете местами на
и на
, результат не будет отличаться, но это может быть, если вы измените plus ()
на следующее:
eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6IiMgRGVmaW5lIGBwbHVzKClgIHdpdGggcmVxdWlyZWQgYXJndW1lbnRzXG5kZWYhl000siSiCyhlxGx1lbnRzXG5kZWYhlxGx2
Аргументы ключевого слова
Если вы хотите убедиться, что вы вызываете все параметры в правильном порядке, вы можете использовать аргументы ключевого слова в вызове функции.Вы используете их, чтобы идентифицировать аргументы по их имени параметра. Чтобы прояснить это, возьмем пример сверху:
eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6IiMgRGVmaW5lIGBwbHVzKClgIGZ1bmN0aW9uXG5kZWYgcGx1cyhhLGIpOlxuICByZXR1cm4gYSArIGJcbiAgXG4jIENhbGwgYHBsdXMoKWAgZnVuY3Rpb24gd2l0aCBwYXJhbWV0ZXJzIFxucGx1cygyLDMpXG5cbiMgQ2FsbCBgcGx1cygpYCBmdW5jdGlvbiB3aXRoIGtleXdvcmQgYXJndW1lbnRzXG5wbHVzKGE9MSwgYj0yKSJ9
Обратите внимание, что, используя аргументы ключевого слова, вы также можете переключать порядок параметров и по-прежнему получать тот же результат при выполнении своей функции:
eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6IiMgRGVmaW5lIGBwbHVzKClgIGZ1bmN0aW9uXG5kZWYgcGx1cyhhLGIpOlxuICByZXR1cm4gYSArIGJcbiAgXG4jIENhbGwgYHBsdXMoKWAgZnVuY3Rpb24gd2l0aCBrZXl3b3JkIGFyZ3VtZW50c1xucGx1cyhiPTIsIGE9MSkifQ ==
Переменное количество аргументов
В тех случаях, когда вы не знаете точное количество аргументов, которые хотите передать функции, вы можете использовать следующий синтаксис с * args
:
eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6IiMgRGVmaW5lIGBwbHVzKClgIGZ1bmN0aW9uIHRvIGFjY2VwdCBhIHZhcmlhYmxlIG51bWJlciBvZiBhcmd1bWVudHNcbmRlZiBwbHVzKCphcmdzKTpcbiAgcmV0dXJuIHN1bShhcmdzKVxuXG4jIENhbGN1bGF0ZSB0aGUgc3VtXG5wbHVzKDEsNCw1KSJ9
Звездочка ( *
) помещается перед именем переменной, которая содержит значения всех аргументов переменных, не являющихся ключевыми словами.Обратите внимание, что вы также могли передать * varint
, * var_int_args
или любое другое имя функции plus ()
.
Совет : попробуйте заменить * args
другим именем, содержащим звездочку. Вы увидите, что приведенный выше код продолжает работать!
Вы видите, что в приведенной выше функции используется встроенная функция Python sum ()
для суммирования всех аргументов, которые передаются в plus ()
. Если вы хотите избежать этого и создать функцию полностью самостоятельно, вы можете использовать эту альтернативу:
eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6IiMgRGVmaW5lIGBwbHVzKClgIGZ1bmN0aW9uIHRvIGFjY2VwdCBhIHZhcmlhYmxlIG51bWJlciBvZiBhcmd1bWVudHNcbmRlZiBwbHVzKCphcmdzKTpcbiAgdG90YWwgPSAwXG4gIGZvciBpIGluIGFyZ3M6XG4gICAgdG90YWwgKz0gaVxuICByZXR1cm4gdG90YWxcblxuIyBDYWxjdWxhdGUgdGhlIHN1bSAgXG5wbHVzKDIwLDMwLDQwLDUwKSJ9
Глобальные и локальные переменные
Как правило, переменные, определенные внутри тела функции, имеют локальную область видимости, а переменные, определенные вне ее, имеют глобальную область видимости.Это означает, что локальные переменные определены в функциональном блоке и могут быть доступны только внутри этой функции, в то время как глобальные переменные могут быть получены всеми функциями, которые могут быть в вашем скрипте:
eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6IiMgR2xvYmFsIHZhcmlhYmxlIGBpbml0YFxuaW5pdCA9IDFcblxuIyBEZWZpbmUgYHBsdXMoKWAgZnVuY3Rpb24gdG8gYWNjZXB0IGEgdmFyaWFibGUgbnVtYmVyIG9mIGFyZ3VtZW50c1xuZGVmIHBsdXMoKmFyZ3MpOlxuICAjIExvY2FsIHZhcmlhYmxlIGBzdW0oKWBcbiAgdG90YWwgPSAwXG4gIGZvciBpIGluIGFyZ3M6XG4gICAgdG90YWwgKz0gaVxuICByZXR1cm4gdG90YWxcbiAgXG4jIEFjY2VzcyB0aGUgZ2xvYmFsIHZhcmlhYmxlXG5wcmludChcInRoaXMgaXMgdGhlIGluaXRpYWxpemVkIHZhbHVlIFwiICsgc3RyKGluaXQpKVxuXG4jIChUcnkgdG8pIGFjY2VzcyB0aGUgbG9jYWwgdmFyaWFibGVcbnByaW50KFwidGhpcyBpcyB0aGUgc3VtIFwiICsgc3RyKHRvdGFsKSkifQ ==
Вы увидите, что получите NameError
, который говорит, что имя 'total' не определено
, когда вы попытаетесь распечатать локальную переменную total
, которая была определена внутри тела функции.Напротив, переменную init
можно без проблем распечатать.
Анонимные функции в Python
Анонимные функции также называются лямбда-функциями в Python, потому что вместо их объявления со стандартным ключевым словом def
вы используете ключевое слово lambda
.
eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6ImRvdWJsZSA9IGxhbWJkYSB4OiB4KjJcblxuZG91YmxlKDUpIn0 =
В приведенном выше фрагменте DataCamp Light lambda x: x * 2
— это анонимная или лямбда-функция. x
— это аргумент, а x * 2
— это выражение или инструкция, которые оцениваются и возвращаются. Особенностью этой функции является то, что у нее нет имени, как в примерах, которые вы видели в первой части этого руководства по функциям. Если бы вам пришлось написать указанную выше функцию в UDF, результат был бы следующим:
def double (x):
возврат x * 2
Рассмотрим еще один пример лямбда-функции, в которой вы работаете с двумя аргументами:
eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6IiMgYHN1bSgpYCBsYW1iZGEgZnVuY3Rpb25cbnN1bSA9IGxhbWJkYSB4LCB5OiB4ICsgeTtcblxuIyBDYWxsIHRoZSBgc3VtKClgIGFub255bW91cyBmdW5jdGlvblxuc3VtKDQsNSlcblxuIyBcIlRyYW5zbGF0ZVwiIHRvIGEgVURGXG5kZWYgc3VtKHgsIHkpOlxuICByZXR1cm4geCt5In0 =
Вы используете анонимные функции, когда вам требуется безымянная функция на короткий период времени, которая создается во время выполнения.Конкретные контексты, в которых это будет актуально, — это когда вы работаете с filter ()
, map ()
и reduce ()
:
eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6ImZyb20gZnVuY3Rvb2xzIGltcG9ydCByZWR1Y2VcblxubXlfbGlzdCA9IFsxLDIsMyw0LDUsNiw3LDgsOSwxMF1cblxuIyBVc2UgbGFtYmRhIGZ1bmN0aW9uIHdpdGggYGZpbHRlcigpYFxuZmlsdGVyZWRfbGlzdCA9IGxpc3QoZmlsdGVyKGxhbWJkYSB4OiAoeCoyID4gMTApLCBteV9saXN0KSlcblxuIyBVc2UgbGFtYmRhIGZ1bmN0aW9uIHdpdGggYG1hcCgpYFxubWFwcGVkX2xpc3QgPSBsaXN0KG1hcChsYW1iZGEgeDogeCoyLCBteV9saXN0KSlcblxuIyBVc2UgbGFtYmRhIGZ1bmN0aW9uIHdpdGggYHJlZHVjZSgpYFxucmVkdWNlZF9saXN0ID0gcmVkdWNlKGxhbWJkYSB4LCB5OiB4K3ksIG15X2xpc3QpXG5cbnByaW50KGZpbHRlcmVkX2xpc3QpXG5wcmludChtYXBwZWRfbGlzdClcbnByaW50KHJlZHVjZWRfbGlzdCkifQ ==
Функция filter ()
фильтрует, как следует из названия, исходный список ввода my_list
на основе критерия > 10
.С другой стороны, с помощью map ()
вы применяете функцию ко всем элементам списка my_list
. В этом случае вы умножаете все элементы на 2
.
Обратите внимание, что функция reduce ()
является частью библиотеки functools
. Вы используете эту функцию кумулятивно для элементов списка my_list
слева направо и сокращаете последовательность до одного значения, в данном случае 55
.
Использование
main ()
в качестве функции Если у вас есть опыт работы с другими языками программирования, такими как Java, вы знаете, что для выполнения функций требуется основная функция
.Как вы видели в приведенных выше примерах, это не обязательно для Python. Однако включение функции main ()
в вашу программу Python может быть полезным для логической структурирования вашего кода — все наиболее важные компоненты содержатся в этой функции main ()
.
Вы можете легко определить функцию main ()
и вызвать ее так же, как вы делали со всеми другими функциями, указанными выше:
eyJsYW5ndWFnZSI6InB5dGhvbiIsInByZV9leGVyY2lzZV9jb2RlIjoiZGVmIGhlbGxvKCk6XG4gIHByaW50KFwiSGVsbG8gV29ybGRcIikgXG4gIHJldHVybiAiLCJzYW1wbGUiOiIjIERlZmluZSBgbWFpbigpYCBmdW5jdGlvblxuZGVmIG1haW4oKTpcbiAgaGVsbG8oKVxuICBwcmludChcIlRoaXMgaXMgYSBtYWluIGZ1bmN0aW9uXCIpXG5cbm1haW4oKSJ9
Однако в нынешнем виде код вашей функции main ()
будет вызываться, когда вы импортируете ее как модуль.Чтобы этого не произошло, вы вызываете функцию main ()
, когда __name__ == '__main__'
.
Это означает, что код вышеупомянутого фрагмента кода становится:
eyJsYW5ndWFnZSI6InB5dGhvbiIsInByZV9leGVyY2lzZV9jb2RlIjoiZGVmIGhlbGxvKCk6XG4gIHByaW50KFwiSGVsbG8gV29ybGRcIikgXG4gIHJldHVybiAiLCJzYW1wbGUiOiIjIERlZmluZSBgbWFpbigpYCBmdW5jdGlvblxuZGVmIG1haW4oKTpcbiAgaGVsbG8oKVxuICBwcmludChcIlRoaXMgaXMgYSBtYWluIGZ1bmN0aW9uXCIpXG4gIFxuIyBFeGVjdXRlIGBtYWluKClgIGZ1bmN0aW9uIFxuaWYgX19uYW1lX18gPT0gJ19fbWFpbl9fJzpcbiAgICBtYWluKCkifQ ==
Обратите внимание на , что помимо функции __main__
у вас также есть функция __init__
, которая инициализирует экземпляр класса или объекта.Проще говоря, он действует как конструктор или инициализатор и автоматически вызывается при создании нового экземпляра класса. С помощью этой функции вновь созданный объект назначается параметру self, который вы видели ранее в этом руководстве. Взгляните на следующий пример:
Класс Собака:
"" "
Требует:
ноги - Ноги, чтобы собака могла ходить.
color - цвет меха.
"" "
def __init __ (я, ноги, цвет):
себя.ноги = ноги
self.color = цвет
def кора (сам):
bark = "кора" * 2
ответный лай
если __name__ == "__main__":
dog = Собака (4, «коричневый»)
лай = dog.bark ()
печать (кора)
Хотите практиковаться дальше?
Поздравляю! Вы прошли это короткое руководство по функциям в Python. Если вы хотите пересмотреть другие базовые материалы по программированию на Python, не пропустите курс Data Types for Data Science, в котором вы обобщите и попрактикуетесь в своих знаниях о списках, словарях, кортежах, наборах и датах.
функций Python (с примерами)
Python включает множество встроенных функций. Эти функции выполняют заранее определенную задачу и могут быть вызваны в любой программе в соответствии с требованиями. Однако, если вы не найдете подходящей встроенной функции для вашей цели, вы можете определить ее. Теперь мы увидим, как определять и использовать функцию в программе Python.
Определение функции
Функция — это многократно используемый блок программных операторов, предназначенный для выполнения определенной задачи.Для определения функции Python предоставляет ключевое слово def
. Ниже приводится синтаксис определения функции.
def имя_функции (параметры): "" "строка документации" "" заявление1 заявление2 ... ... возврат [выражение]
За ключевым словом def
следует подходящий идентификатор в качестве имени функции и круглые скобки.Один или несколько параметров могут быть указаны в круглых скобках по желанию. Символ :
после круглых скобок начинает блок с отступом.
Первым оператором в теле функции может быть строка, которая называется строкой документации
. Он объясняет функциональность функции / класса.
Строка документации не является обязательной.
Тело функции содержит один или несколько операторов, выполняющих некоторые действия.Он также может использовать ключевое слово pass.
Необязательно, последний оператор в функциональном блоке — это оператор возврата. Он отправляет управление выполнением обратно в среду. Если выражение добавляется перед return, его значение также возвращается в вызывающий код.
В следующем примере определяется функция greet ()
.
def greet ():
"" "Эта функция отображает" Hello World! "" ""
print ('Привет, мир!')
Выше мы определили функцию greet ()
.Первый оператор — это строка документации, в которой упоминается, что делает эта функция. Второй подобный метод — это метод печати, который выводит указанную строку на консоль.
Обратите внимание, что в нем нет оператора возврата.
Чтобы вызвать определенную функцию, просто используйте ее имя как оператор в любом месте кода.
Например, указанная выше функция может быть вызвана с использованием круглых скобок, greet ()
.
По умолчанию все функции возвращают Нет
, если оператор return не существует.
Функция help () отображает строку документации, как показано ниже.
>>> помогите (привет)
Справка по функции приветствия в модуле __main__:
приветствовать()
Эта функция отображает "Hello World!"
Параметры функции
Можно определить функцию для получения одного или нескольких параметров (также называемых аргументами) и использования их для обработки внутри функционального блока.Параметрам / аргументам можно дать подходящие формальные имена. Функция greet ()
теперь определена для получения строкового параметра с именем name
. Внутри функции оператор print ()
модифицируется для отображения приветственного сообщения, адресованного полученному параметру.
def greet (имя):
print ('Привет', имя)
greet ('Steve') # вызываем функцию с аргументом
приветствовать (123)
Имена аргументов, используемых в определении функции, называются формальными аргументами / параметрами.Объекты, фактически используемые при вызове функции, называются фактическими аргументами / параметрами.
Параметры функции могут иметь аннотацию для указания типа параметра с использованием синтаксиса параметр: тип
. Например, следующее аннотирует строку типа параметра.
def приветствие (name: str):
print ('Привет', имя)
greet ('Steve') # вызываем функцию со строковым аргументом
greet (123) # вызвать ошибку для аргумента int
Несколько параметров
Функция может иметь несколько параметров.Следующая функция принимает три аргумента.
def greet (имя1, имя2, имя3):
print ('Привет', имя1, ',', имя2, 'и', имя3)
greet ('Steve', 'Bill', 'Yash') # вызываем функцию со строковым аргументом
Привет, Стив, Билл и Яш
Неизвестное количество аргументов
Функция в Python может иметь неизвестное количество аргументов, если перед параметром поставить *
, если вы не знаете количество аргументов, которые пользователь собирается передать.
def привет (* имена):
print ('Привет', имена [0], ',', имена [1], ',', имена [3])
привет (Стив, Билл, Яш)
Привет, Стив, Билл и Яш
Следующая функция работает с любым количеством аргументов.
def привет (* имена):
я = 0
print ('Привет', конец = '')
а len (имена)> i:
print (имена [i], end = ',')
я + = 1
привет (Стив, Билл, Яш)
привет ('Стив', 'Билл', 'Яш', 'Капил', 'Джон', 'Амир')
Привет Стив, Билл, Яш,
Привет, Стив, Билл, Яш, Капил, Джон, Амир
Функция с аргументами ключевого слова
Чтобы вызвать функцию с аргументами, необходимо предоставить такое же количество фактических аргументов.Однако функция может быть вызвана путем передачи значений параметров с использованием имен параметров в любом порядке. Например, следующие значения передаются с использованием имен параметров.
def greet (имя, фамилия):
print ('Привет', имя, фамилия)
greet (lastname = 'Jobs', firstname = 'Steve') # передача параметров в любом порядке с использованием аргумента ключевого слова
Аргумент ключевого слова ** kwarg
Функция может иметь один параметр с префиксом **
.Этот тип параметра инициализируется новым упорядоченным отображением, получающим любые лишние аргументы ключевого слова, по умолчанию используется новое пустое отображение того же типа.
def привет (** человек):
print ('Привет', человек ['имя'], человек ['фамилия'])
приветствую (firstname = 'Steve', lastname = 'Jobs')
приветствую (lastname = 'Jobs', firstname = 'Steve')
привет (firstname = 'Bill', lastname = 'Gates', возраст = 55)
greet (firstname = 'Bill') # вызывает ошибку KeyError
Привет, Стив Джобс
Привет, Стив Джобс
Привет Билл Гейтс
При использовании параметра **
порядок аргументов не имеет значения.Однако названия аргументов должны быть такими же.
Получите доступ к значению аргументов ключевого слова, используя paramter_name ['keyword_argument']
.
Если функция обращается к аргументу ключевого слова, но вызывающий код не передает этот аргумент ключевого слова, то она вызовет исключение KeyError
, как показано ниже.
def привет (** человек):
print ('Привет', человек ['имя'], человек ['фамилия'])
greet (firstname = 'Bill') # вызывает ошибку KeyError, необходимо предоставить аргумент 'lastname'
Traceback (последний звонок последний):
Файл "", строка 1, в
приветствовать (firstname = 'Bill')
Файл "", строка 2, в приветствии
print ('Привет', человек ['имя'], человек ['фамилия'])
KeyError: "фамилия"
Параметр со значением по умолчанию
При определении функции ее параметрам могут быть присвоены значения по умолчанию.Это значение по умолчанию заменяется, если при вызове функции передается соответствующий фактический аргумент. Однако, если фактический аргумент не указан, внутри функции будет использоваться значение по умолчанию.
Следующая функция greet ()
определяется параметром name
, имеющим значение по умолчанию 'Guest'
.
Он будет заменен только в том случае, если будет передан какой-либо фактический аргумент.
def greet (name = 'Гость'):
print ('Привет', имя)
приветствовать()
привет ('Стив')
Функция с возвращаемым значением
В большинстве случаев нам нужен результат функции, который будет использоваться в дальнейших процессах. Следовательно, когда функция возвращается, она также должна возвращать значение.
Пользовательская функция также может возвращать значение в вызывающую среду, помещая выражение перед оператором return. В этом случае возвращаемое значение должно быть присвоено некоторой переменной.
def sum (a, b):
вернуть a + b
Вышеупомянутая функция может быть вызвана и ей присвоено значение, как показано ниже.
итого = сумма (10, 20)
печать (всего)
итог = сумма (5, сумма (10, 20))
печать (всего)
.