Функции

Введение

Примеры

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

    Использование def утверждения является наиболее распространенным способом определить функцию в Python. Это утверждение так называемое соединение заявление одного пункта со следующим синтаксисом:

     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.

    Функция , которая достигает конца исполнения без оператора возврата всегда будет возвращать 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 
  • Определение функции с необязательными аргументами

    Дополнительные аргументы могут быть определены путем назначения ( с использованием = ) значение по умолчанию имя-аргумента:

     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 это простой родной словарь питона. Например, args['value1'] даст значение аргумента value1 . Обязательно проверьте заранее , что есть такой аргумент или KeyError будет поднят.

    Предупреждение

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

    Позиционные / ключевые аргументы приходят в первую очередь. (Обязательные аргументы). Тогда приходит произвольные *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 должен быть последним параметром. Попытка использовать более одного либо приведет к исключению ошибок синтаксиса.

    Замечание о функциях вложения с необязательными аргументами

    Можно гнездовые такие функции и обычная условность, чтобы удалить элементы , что код уже обрабатываемые , но если вы передаете вниз параметры , которые нужно передать дополнительные позиционные аргументы с * префиксом и необязательной ключевыми словами арг с ** приставкой , иначе аргументы будут передаваться как список или кортеж, а 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]
    
     

    Примечание: Некоторые Иды как PyCharm будет выдавать предупреждение , когда изменяемый тип задан как атрибут по умолчанию.

    Решение

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

    Общая идиома , чтобы достичь этого , когда изменяемый типа необходим по умолчанию, является не использовать None (неизменный) в качестве аргумента по умолчанию , а затем присвоить фактическое значение по умолчанию для переменного аргумента , если оно равно None .

     def append(elem, to=None):
        if to is None:
            to = []
    
        to.append(elem)
        return to
    
     
  • Лямбда (встроенные / анонимные) функции

    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 - ы обычно используются для коротких функций, которые удобно определить в точке , где они называются ( как правило , с 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) не рекомендуется назначать лямбды переменным (как мы это делали в первых двух примерах):

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

    Сначала немного терминологии:

    • аргумент (фактический параметр): фактическая переменная передается в функцию;
    • Параметр (формальный параметр): принимающая переменная, которая используется в функции.

    В 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 заявление ( https://codecamp.ru/documentation/python/263/variable-scope-and-binding/5712/nonlocal-variables#t=201608272008282346874 ) для реализации полного закрытия с вложенными функциями.

    def makeInc (x): def inc (y): нелокальный x # теперь можно присвоить значение x x + = y вернуть x return inc incOne = makeInc (1) incOne (5) # возвращает 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 
  • Рекурсивная лямбда с использованием присвоенной переменной

    

Синтаксис

Параметры

Примечания