Python Language
функции
Поиск…
Вступление
Функции в Python предоставляют организованный, многоразовый и модульный код для выполнения ряда конкретных действий. Функции упрощают процесс кодирования, предотвращают избыточную логику и упрощают выполнение кода. В этом разделе описывается декларация и использование функций в Python.
Python имеет множество встроенных функций, таких как print()
, input()
, len()
. Помимо встроенных модулей вы также можете создавать свои собственные функции для выполнения более конкретных заданий - это называемые пользовательскими функциями .
Синтаксис
- def function_name ( arg1, ... argN, * args, kw1, kw2 = default, ..., ** kwargs ): statements
- lambda arg1, ... argN, * args, kw1, kw2 = default, ..., ** kwargs : выражение
параметры
параметр | подробности |
---|---|
arg1 , ..., argN | Обычные аргументы |
* арг | Без названия позиционные аргументы |
kw1 , ..., kwN | Ключ-только аргументы |
** kwargs | Остальные аргументы ключевого слова |
замечания
5 основных вещей, которые вы можете выполнять с функциями:
Назначение функций переменным
def f(): print(20) y = f y() # Output: 20
Определить функции внутри других функций ( вложенные функции )
def f(a, b, y): def inner_add(a, b): # inner_add is hidden from outer code return a + b return inner_add(a, b)**y
Функции могут возвращать другие функции
def f(y): def nth_power(x): return x ** y return nth_power # returns a function squareOf = f(2) # function that returns the square of a number cubeOf = f(3) # function that returns the cube of a number squareOf(3) # Output: 9 cubeOf(2) # Output: 8
Функции могут передаваться как параметры для других функций
def a(x, y): print(x, y) def b(fun, str): # b has two arguments: a function and a string fun('Hello', str) b(a, 'Sophia') # Output: Hello Sophia
Внутренние функции имеют доступ к охватывающей области ( Closure )
def outer_fun(name): def inner_fun(): # the variable name is available to the inner function return "Hello "+ name + "!" return inner_fun greet = outer_fun("Sophia") print(greet()) # Output: Hello Sophia!
Дополнительные ресурсы
- Подробнее о функциях и декораторах: https://www.thecodeship.com/patterns/guide-to-python-function-decorators/
Определение и вызов простых функций
Использование инструкции def
является наиболее распространенным способом определения функции в python. Этот оператор представляет собой так называемый составной оператор single clause со следующим синтаксисом:
def function_name(parameters):
statement(s)
function_name
известно как идентификатор функции. Поскольку определение функции является исполняемым оператором, его выполнение связывает имя функции с функциональным объектом, который может быть вызван позже при использовании идентификатора.
parameters
- это необязательный список идентификаторов, которые привязаны к значениям, указанным в качестве аргументов при вызове функции. Функция может иметь произвольное число аргументов, разделенных запятыми.
statement(s)
- также известный как тело функции - это непустая последовательность операторов, выполняемых каждый раз при вызове функции. Это означает, что тело функции не может быть пустым, как и любой отложенный блок .
Вот пример простого определения функции, целью которого является печать Hello
каждый раз, когда он вызывается:
def greet():
print("Hello")
Теперь давайте назовем определенную функцию greet()
:
greet()
# Out: Hello
Это еще один пример определения функции, который принимает один единственный аргумент и отображает переданное значение при каждом вызове функции:
def greet_two(greeting):
print(greeting)
После этого greet_two()
должна вызываться с аргументом:
greet_two("Howdy")
# Out: Howdy
Также вы можете указать значение по умолчанию для этого аргумента функции:
def greet_two(greeting="Howdy"):
print(greeting)
Теперь вы можете вызвать функцию без значения:
greet_two()
# Out: Howdy
Вы заметите, что в отличие от многих других языков вам не нужно явно объявлять возвращаемый тип функции. Функции Python могут возвращать значения любого типа с помощью ключевого слова return
. Одна функция может возвращать любое количество различных типов!
def many_types(x):
if x < 0:
return "Hello!"
else:
return 0
print(many_types(1))
print(many_types(-1))
# Output:
0
Hello!
Пока это правильно обрабатывается вызывающим, это вполне допустимый код Python.
Функция, которая достигает конца выполнения без оператора return, всегда будет возвращать None
:
def do_nothing():
pass
print(do_nothing())
# Out: None
Как упоминалось ранее, определение функции должно иметь тело функции, непустую последовательность операторов. Поэтому инструкция pass
используется как тело функции, которая является пустой операцией - когда она выполняется, ничего не происходит. Он делает то, что это значит, он пропускает. Он полезен в качестве заполнителя, если оператор требуется синтаксически, но код не должен выполняться.
Возвращаемые значения из функций
Функции могут return
значение, которое вы можете использовать напрямую:
def give_me_five():
return 5
print(give_me_five()) # Print the returned value
# Out: 5
или сохранить значение для последующего использования:
num = give_me_five()
print(num) # Print the saved returned value
# Out: 5
или использовать значение для любых операций:
print(give_me_five() + 10)
# Out: 15
Если в функции встречается return
функция будет немедленно выведена, и последующие операции не будут оцениваться:
def give_me_another_five():
return 5
print('This statement will not be printed. Ever.')
print(give_me_another_five())
# Out: 5
Вы также можете return
несколько значений (в виде кортежа):
def give_me_two_fives():
return 5, 5 # Returns two 5
first, second = give_me_two_fives()
print(first)
# Out: 5
print(second)
# Out: 5
Функция без оператора return
неявно возвращает None
. Аналогично функция с оператором return
, но никакое возвращаемое значение или переменная не возвращает None
.
Определение функции с аргументами
Аргументы определяются в круглых скобках после имени функции:
def divide(dividend, divisor): # The names of the function and its arguments
# The arguments are available by name in the body of the function
print(dividend / divisor)
Имя функции и ее список аргументов называются сигнатурой функции. Каждый именованный аргумент является фактически локальной переменной функции.
При вызове функции дайте значения для аргументов, указав их в порядке
divide(10, 2)
# output: 5
или указать их в любом порядке, используя имена из определения функции:
divide(divisor=2, dividend=10)
# output: 5
Определение функции с необязательными аргументами
Необязательные аргументы могут быть определены путем присвоения (using =
) значения по умолчанию для имени-аргумента:
def make(action='nothing'):
return action
Вызов этой функции возможен тремя различными способами:
make("fun")
# Out: fun
make(action="sleep")
# Out: sleep
# The argument is optional so the function will use the default value if the argument is
# not passed in.
make()
# Out: nothing
Предупреждение
Уменяемые типы (
list
,dict
,set
и т. Д.) Следует относиться с осторожностью, когда они заданы как атрибут по умолчанию . Любая мутация аргумента по умолчанию изменяет его навсегда. См. Раздел Определение функции с необязательными изменяемыми аргументами .
Определение функции с несколькими аргументами
Можно дать функцию столько аргументов, сколько нужно, единственными фиксированными правилами являются то, что каждое имя аргумента должно быть уникальным, а необязательные аргументы должны быть после необязательных:
def func(value1, value2, optionalvalue=10):
return '{0} {1} {2}'.format(value1, value2, optionalvalue1)
При вызове функции вы можете либо указать каждое ключевое слово без имени, но затем порядок:
print(func(1, 'a', 100))
# Out: 1 a 100
print(func('abc', 14))
# abc 14 10
Или объедините аргументы с именем и без. Тогда те, у кого есть имя, должны следовать за ними, но порядок имен с именем не имеет значения:
print(func('This', optionalvalue='StackOverflow Documentation', value2='is'))
# Out: This is StackOverflow Documentation
Определение функции с произвольным числом аргументов
Произвольное число позиционных аргументов:
Определение функции, способной принимать произвольное количество аргументов, может быть выполнено путем префикса одного из аргументов с помощью *
def func(*args):
# args will be a tuple containing all values that are passed in
for i in args:
print(i)
func(1, 2, 3) # Calling it with 3 arguments
# Out: 1
# 2
# 3
list_of_arg_values = [1, 2, 3]
func(*list_of_arg_values) # Calling it with list of values, * expands the list
# Out: 1
# 2
# 3
func() # Calling it without arguments
# No Output
Вы не можете предоставить значение по умолчанию для args
, например func(*args=[1, 2, 3])
повысит синтаксическую ошибку (даже не компилируется).
Вы не можете предоставить их по имени при вызове функции, например func(*args=[1, 2, 3])
приведет к созданию TypeError
.
Но если у вас уже есть аргументы в массиве (или любой другой Iterable
), вы можете вызвать свою функцию следующим образом: func(*my_stuff)
.
К этим аргументам ( *args
) можно обращаться по индексу, например args[0]
вернет первый аргумент
Произвольное количество аргументов ключевого слова
Вы можете взять произвольное количество аргументов с именем, определив аргумент в определении с двумя *
перед ним:
def func(**kwargs):
# kwargs will be a dictionary containing the names as keys and the values as values
for name, value in kwargs.items():
print(name, value)
func(value1=1, value2=2, value3=3) # Calling it with 3 arguments
# Out: value1 1
# value2 2
# value3 3
func() # Calling it without arguments
# No Out put
my_dict = {'foo': 1, 'bar': 2}
func(**my_dict) # Calling it with a dictionary
# Out: foo 1
# bar 2
Вы не можете предоставить их без имен, например func(1, 2, 3)
поднимет TypeError
.
kwargs
- простой родной словарь python. Например, args['value1']
даст значение для аргумента value1
. Обязательно проверьте заранее, что есть такой аргумент или KeyError
будет поднят.
Предупреждение
Вы можете смешивать их с другими необязательными и необходимыми аргументами, но порядок в определении имеет значение.
Первыми должны быть аргументы positional / keyword . (Необходимые аргументы).
Затем идут произвольные аргументы *arg
. (Необязательный).
Затем следуют аргументы только для ключевого слова . (Необходимые).
Наконец, возникает произвольное ключевое слово **kwargs
. (Необязательный).
# |-positional-|-optional-|---keyword-only--|-optional-|
def func(arg1, arg2=10 , *args, kwarg1, kwarg2=2, **kwargs):
pass
-
arg1
, в противном случае возникаетTypeError
. Он может быть задан как позиционный (func(10)
) или аргумент ключевого слова (func(arg1=10)
). -
kwarg1
также должен быть указан, но он может быть предоставлен только в качестве ключевого слова:func(kwarg1=10)
. -
arg2
иkwarg2
являются необязательными. Если значение должно быть изменено, применяются те же правила, что и дляarg1
(либо позиционный, либо ключевое слово), либоkwarg1
(только ключевое слово). -
*args
ловит дополнительные позиционные параметры. Но учтите, чтоarg1
иarg2
должны быть представлены как позиционные аргументы для передачи аргументов в*args
:func(1, 1, 1, 1)
. -
**kwargs
ловит все дополнительные параметры ключевых слов. В этом случае любой параметр, который не являетсяarg1
,arg2
,kwarg1
илиkwarg2
. Например:func(kwarg3=10)
. - В Python 3 вы можете использовать
*
самостоятельно, чтобы указать, что все последующие аргументы должны быть указаны как ключевые слова. Например, функцияmath.isclose
в Python 3.5 и выше определяется с помощьюdef math.isclose (a, b, *, rel_tol=1e-09, abs_tol=0.0)
, что означает, что первые два аргумента могут быть поставлены позиционно, но необязательный третий и четвертый параметры могут поставляться только в качестве аргументов ключевого слова.
Python 2.x не поддерживает параметры только для ключевого слова. Такое поведение можно эмулировать с помощью kwargs
:
def func(arg1, arg2=10, **kwargs):
try:
kwarg1 = kwargs.pop("kwarg1")
except KeyError:
raise TypeError("missing required keyword-only argument: 'kwarg1'")
kwarg2 = kwargs.pop("kwarg2", 2)
# function body ...
Примечание о присвоении имен
Условность наименования необязательных позиционных аргументов args
и необязательных аргументы ключевых слов kwargs
просто условность вы можете использовать любые имена вам нравится , но это полезно следовать соглашению , чтобы другие знали , что вы делаете, или даже сам потом так пожалуйста.
Примечание о уникальности
Любая функция может быть определена без одного или одного *args
и ни одного, ни одного **kwargs
но не с более чем одним из них. Также *args
должен быть последним позиционным аргументом, а **kwargs
должен быть последним параметром. Попытка использовать более одного из них приведет к исключению ошибки синтаксиса.
Примечание о функциях вложенности с необязательными аргументами
Можно использовать такие функции, и обычным соглашением является удаление элементов, которые уже обработал код, но если вы передаете параметры, вам необходимо передать необязательные позиционные аргументы с префиксом *
и необязательными ключевыми словами args с префиксом **
, иначе args передаются как список или кортеж, а kwargs - как один словарь. например:
def fn(**kwargs):
print(kwargs)
f1(**kwargs)
def f1(**kwargs):
print(len(kwargs))
fn(a=1, b=2)
# Out:
# {'a': 1, 'b': 2}
# 2
Определение функции с необязательными изменяемыми аргументами
Существует проблема при использовании необязательных аргументов с изменяемым типом по умолчанию (описанным в разделе «Определение функции с необязательными аргументами» ), что потенциально может привести к неожиданному поведению.
объяснение
Эта проблема возникает из-за того, что аргументы по умолчанию функции инициализируются один раз , в момент, когда функция определена , а не (как и многие другие языки) при вызове функции. Значения по умолчанию хранятся внутри переменной-члена __defaults__
объекта функции.
def f(a, b=42, c=[]):
pass
print(f.__defaults__)
# Out: (42, [])
Для неизменяемых типов (см. Прохождение аргументации и изменчивость ) это не проблема, потому что нет способа изменить эту переменную; его можно только переназначить, оставив исходное значение без изменений. Следовательно, последующие гарантированно имеют одинаковое значение по умолчанию. Однако для изменяемого типа исходное значение может мутировать, выполняя вызовы его различных функций-членов. Поэтому для последовательных вызовов функции не гарантируется первоначальное значение по умолчанию.
def append(elem, to=[]):
to.append(elem) # This call to append() mutates the default variable "to"
return to
append(1)
# Out: [1]
append(2) # Appends it to the internally stored list
# Out: [1, 2]
append(3, []) # Using a new created list gives the expected result
# Out: [3]
# Calling it again without argument will append to the internally stored list again
append(4)
# Out: [1, 2, 4]
Примечание. Некоторые IDE, такие как PyCharm, выдают предупреждение, если в качестве атрибута по умолчанию указан изменяемый тип.
Решение
Если вы хотите, чтобы аргумент по умолчанию всегда был тем, который вы указываете в определении функции, тогда решение всегда должно использовать неизменяемый тип в качестве аргумента по умолчанию.
Общей идиомой для достижения этого, когда изменяемый тип необходим по умолчанию, заключается в том, чтобы использовать None
(immutable) в качестве аргумента по умолчанию, а затем присваивать фактическое значение по умолчанию переменной аргумента, если оно равно None
.
def append(elem, to=None):
if to is None:
to = []
to.append(elem)
return to
Функции Lambda (Inline / Anonymous)
Ключевое слово lambda
создает встроенную функцию, содержащую одно выражение. Значение этого выражения - это то, что функция возвращает при вызове.
Рассмотрим функцию:
def greeting():
return "Hello"
который, когда он называется:
print(greeting())
печатает:
Hello
Это можно записать в виде лямбда-функции следующим образом:
greet_me = lambda: "Hello"
См. Примечание в нижней части этого раздела о назначении лямбда для переменных. Как правило, не делайте этого.
Это создает встроенную функцию с именем greet_me
которое возвращает Hello
. Обратите внимание, что вы не записываете return
при создании функции с лямбдой. Значение после :
автоматически возвращается.
После присвоения переменной она может использоваться как обычная функция:
print(greet_me())
печатает:
Hello
lambda
s также может принимать аргументы:
strip_and_upper_case = lambda s: s.strip().upper()
strip_and_upper_case(" Hello ")
возвращает строку:
HELLO
Они также могут принимать произвольное количество аргументов / аргументов ключевого слова, таких как обычные функции.
greeting = lambda x, *args, **kwargs: print(x, args, kwargs)
greeting('hello', 'world', world='world')
печатает:
hello ('world',) {'world': 'world'}
lambda
s обычно используются для коротких функций, которые удобно определять в том месте, где они вызываются (обычно с sorted
, filter
и map
).
Например, эта строка сортирует список строк, игнорируя их случай и игнорируя пробелы в начале и в конце:
sorted( [" foo ", " bAR", "BaZ "], key=lambda s: s.strip().upper())
# Out:
# [' bAR', 'BaZ ', ' foo ']
Список сортировки просто игнорирует пробелы:
sorted( [" foo ", " bAR", "BaZ "], key=lambda s: s.strip())
# Out:
# ['BaZ ', ' bAR', ' foo ']
Примеры с map
:
sorted( map( lambda s: s.strip().upper(), [" foo ", " bAR", "BaZ "]))
# Out:
# ['BAR', 'BAZ', 'FOO']
sorted( map( lambda s: s.strip(), [" foo ", " bAR", "BaZ "]))
# Out:
# ['BaZ', 'bAR', 'foo']
Примеры с числовыми списками:
my_list = [3, -4, -2, 5, 1, 7]
sorted( my_list, key=lambda x: abs(x))
# Out:
# [1, -2, 3, -4, 5, 7]
list( filter( lambda x: x>0, my_list))
# Out:
# [3, 5, 1, 7]
list( map( lambda x: abs(x), my_list))
# Out:
[3, 4, 2, 5, 1, 7]
Можно вызвать другие функции (с / без аргументов) изнутри лямбда-функции.
def foo(msg):
print(msg)
greet = lambda x = "hello world": foo(x)
greet()
печатает:
hello world
Это полезно, потому что lambda
может содержать только одно выражение и с помощью вспомогательной функции можно запускать несколько операторов.
НОТА
Имейте в виду, что PEP-8 (официальное руководство по стилю Python) не рекомендует назначать lambdas для переменных (как это было в первых двух примерах):
Всегда используйте инструкцию def вместо оператора присваивания, который привязывает лямбда-выражение непосредственно к идентификатору.
Да:
def f(x): return 2*x
Нет:
f = lambda x: 2*x
Первая форма означает, что имя результирующего функционального объекта является специально
f
вместо общего<lambda>
. Это более полезно для отслеживания и представления строк в целом. Использование оператора присваивания исключает единственное преимущество, которое лямбда-выражение может предлагать в явном выраженииdef
(т. Е. Что оно может быть встроено в большее выражение).
Прохождение и изменчивость аргумента
Во-первых, некоторая терминология:
- аргумент ( фактический параметр): фактическая переменная передается функции;
- параметр ( формальный параметр): принимающая переменная, которая используется в функции.
В Python аргументы передаются присваиванием (в отличие от других языков, где аргументы могут передаваться по значению / ссылке / указателю).
Мутирование параметра будет мутировать аргумент (если тип аргумента изменен).
def foo(x): # here x is the parameter x[0] = 9 # This mutates the list labelled by both x and y print(x) y = [4, 5, 6] foo(y) # call foo with y as argument # Out: [9, 5, 6] # list labelled by x has been mutated print(y) # Out: [9, 5, 6] # list labelled by y has been mutated too
Переназначение параметра не приведет к переназначению аргумента.
def foo(x): # here x is the parameter, when we call foo(y) we assign y to x x[0] = 9 # This mutates the list labelled by both x and y x = [1, 2, 3] # x is now labeling a different list (y is unaffected) x[2] = 8 # This mutates x's list, not y's list y = [4, 5, 6] # y is the argument, x is the parameter foo(y) # Pretend that we wrote "x = y", then go to line 1 y # Out: [9, 5, 6]
В Python мы фактически не присваиваем значения переменным, вместо этого связываем (т.е. присваиваем, присоединяем) переменные (считающиеся именами ) к объектам.
- Неизменяемость: целые числа, строки, кортежи и т. Д. Все операции делают копии.
- Mutable: списки, словари, наборы и т. Д. Операции могут или не могут мутировать.
x = [3, 1, 9]
y = x
x.append(5) # Mutates the list labelled by x and y, both x and y are bound to [3, 1, 9]
x.sort() # Mutates the list labelled by x and y (in-place sorting)
x = x + [4] # Does not mutate the list (makes a copy for x only, not y)
z = x # z is x ([1, 3, 9, 4])
x += [6] # Mutates the list labelled by both x and z (uses the extend function).
x = sorted(x) # Does not mutate the list (makes a copy for x only).
x
# Out: [1, 3, 4, 5, 6, 9]
y
# Out: [1, 3, 5, 9]
z
# Out: [1, 3, 5, 9, 4, 6]
закрытие
Замыкания в Python создаются вызовами функций. Здесь вызов makeInc
создает привязку для x
которую ссылается внутри функции inc
. Каждый вызов makeInc
создает новый экземпляр этой функции, но каждый экземпляр имеет ссылку на другую привязку x
.
def makeInc(x):
def inc(y):
# x is "attached" in the definition of inc
return y + x
return inc
incOne = makeInc(1)
incFive = makeInc(5)
incOne(5) # returns 6
incFive(5) # returns 10
Обратите внимание, что при регулярном закрытии закрытая функция полностью наследует все переменные из среды окружения, в этой конструкции закрытая функция имеет только доступ для чтения к унаследованным переменным, но не может назначать им
def makeInc(x):
def inc(y):
# incrementing x is not allowed
x += y
return x
return inc
incOne = makeInc(1)
incOne(5) # UnboundLocalError: local variable 'x' referenced before assignment
Python 3 предлагает nonlocal
оператор ( нелокальные переменные ) для реализации полного закрытия с вложенными функциями.
def makeInc(x):
def inc(y):
nonlocal x
# now assigning a value to x is allowed
x += y
return x
return inc
incOne = makeInc(1)
incOne(5) # returns 6
Рекурсивные функции
Рекурсивная функция - это функция, которая вызывает себя в своем определении. Например, математическая функция, факториал, определяемая factorial(n) = n*(n-1)*(n-2)*...*3*2*1
. может быть запрограммирован как
def factorial(n):
#n here should be an integer
if n == 0:
return 1
else:
return n*factorial(n-1)
выходы здесь:
factorial(0)
#out 1
factorial(1)
#out 1
factorial(2)
#out 2
factorial(3)
#out 6
как и ожидалось. Обратите внимание, что эта функция рекурсивна, потому что второй return factorial(n-1)
, где функция вызывает себя в своем определении.
Некоторые рекурсивные функции могут быть реализованы с использованием лямбда , факториальная функция, использующая лямбда, будет примерно такой:
factorial = lambda n: 1 if n == 0 else n*factorial(n-1)
Функция выводит то же, что и выше.
Предел рекурсии
Существует предел глубине возможной рекурсии, которая зависит от реализации Python. Когда предел достигнут, возникает исключение RuntimeError:
def cursing(depth):
try:
cursing(depth + 1) # actually, re-cursing
except RuntimeError as RE:
print('I recursed {} times!'.format(depth))
cursing(0)
# Out: I recursed 1083 times!
Можно изменить предел глубины рекурсии, используя sys.setrecursionlimit(limit)
и проверить этот предел на sys.getrecursionlimit()
.
sys.setrecursionlimit(2000)
cursing(0)
# Out: I recursed 1997 times!
Из Python 3.5 исключение представляет собой RecursionError
, который получен из RuntimeError
.
Вложенные функции
Функции в python являются первоклассными объектами. Они могут быть определены в любой области
def fibonacci(n):
def step(a,b):
return b, a+b
a, b = 0, 1
for i in range(n):
a, b = step(a, b)
return a
Функции захвата их охватывающей области могут передаваться как любой другой вид объекта
def make_adder(n):
def adder(x):
return n + x
return adder
add5 = make_adder(5)
add6 = make_adder(6)
add5(10)
#Out: 15
add6(10)
#Out: 16
def repeatedly_apply(func, n, x):
for i in range(n):
x = func(x)
return x
repeatedly_apply(add5, 5, 1)
#Out: 26
Итерируемая и распаковка словарей
Функции позволяют указывать эти типы параметров: позиционный, именованный, переменный позиционный, аргументы ключевых слов (kwargs). Вот ясное и краткое использование каждого типа.
def unpacking(a, b, c=45, d=60, *args, **kwargs):
print(a, b, c, d, args, kwargs)
>>> unpacking(1, 2)
1 2 45 60 () {}
>>> unpacking(1, 2, 3, 4)
1 2 3 4 () {}
>>> unpacking(1, 2, c=3, d=4)
1 2 3 4 () {}
>>> unpacking(1, 2, d=4, c=3)
1 2 3 4 () {}
>>> pair = (3,)
>>> unpacking(1, 2, *pair, d=4)
1 2 3 4 () {}
>>> unpacking(1, 2, d=4, *pair)
1 2 3 4 () {}
>>> unpacking(1, 2, *pair, c=3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'c'
>>> unpacking(1, 2, c=3, *pair)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'c'
>>> args_list = [3]
>>> unpacking(1, 2, *args_list, d=4)
1 2 3 4 () {}
>>> unpacking(1, 2, d=4, *args_list)
1 2 3 4 () {}
>>> unpacking(1, 2, c=3, *args_list)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'c'
>>> unpacking(1, 2, *args_list, c=3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'c'
>>> pair = (3, 4)
>>> unpacking(1, 2, *pair)
1 2 3 4 () {}
>>> unpacking(1, 2, 3, 4, *pair)
1 2 3 4 (3, 4) {}
>>> unpacking(1, 2, d=4, *pair)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'd'
>>> unpacking(1, 2, *pair, d=4)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'd'
>>> args_list = [3, 4]
>>> unpacking(1, 2, *args_list)
1 2 3 4 () {}
>>> unpacking(1, 2, 3, 4, *args_list)
1 2 3 4 (3, 4) {}
>>> unpacking(1, 2, d=4, *args_list)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'd'
>>> unpacking(1, 2, *args_list, d=4)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'd'
>>> arg_dict = {'c':3, 'd':4}
>>> unpacking(1, 2, **arg_dict)
1 2 3 4 () {}
>>> arg_dict = {'d':4, 'c':3}
>>> unpacking(1, 2, **arg_dict)
1 2 3 4 () {}
>>> arg_dict = {'c':3, 'd':4, 'not_a_parameter': 75}
>>> unpacking(1, 2, **arg_dict)
1 2 3 4 () {'not_a_parameter': 75}
>>> unpacking(1, 2, *pair, **arg_dict)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'd'
>>> unpacking(1, 2, 3, 4, **arg_dict)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'd'
# Positional arguments take priority over any other form of argument passing
>>> unpacking(1, 2, **arg_dict, c=3)
1 2 3 4 () {'not_a_parameter': 75}
>>> unpacking(1, 2, 3, **arg_dict, c=3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'c'
Принуждение использования именованных параметров
Все параметры, указанные после первой звездочки в сигнатуре функции, являются ключевыми словами.
def f(*a, b):
pass
f(1, 2, 3)
# TypeError: f() missing 1 required keyword-only argument: 'b'
В Python 3 можно поместить единственную звездочку в подпись функции, чтобы гарантировать, что остальные аргументы могут передаваться только с использованием аргументов ключевого слова.
def f(a, b, *, c):
pass
f(1, 2, 3)
# TypeError: f() takes 2 positional arguments but 3 were given
f(1, 2, c=3)
# No error
Рекурсивная Лямбда с использованием назначенной переменной
Один из способов создания рекурсивных лямбда-функций заключается в назначении функции переменной и последующем ее привязке к самой функции. Общим примером этого является рекурсивный расчет факториала числа - например, как показано в следующем коде:
lambda_factorial = lambda i:1 if i==0 else i*lambda_factorial(i-1)
print(lambda_factorial(4)) # 4 * 3 * 2 * 1 = 12 * 2 = 24
Описание кода
Лямбда-функция через назначение переменной передается значение (4), которое оно оценивает и возвращает 1, если оно равно 0, или возвращает текущее значение ( i
) * другое вычисление с помощью лямбда-функции значения - 1 ( i-1
). Это продолжается до тех пор, пока переданное значение не уменьшится до 0 ( return 1
). Процесс, который можно визуализировать как: