Поиск…


Вступление

Функции в 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!
    

Дополнительные ресурсы

Определение и вызов простых функций

Использование инструкции 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 оператор ( нелокальные переменные ) для реализации полного закрытия с вложенными функциями.

Python 3.x 3.0
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 ). Процесс, который можно визуализировать как:

recursive_lambda_path



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow