Поиск…


Назначение деструктуризации

В назначениях вы можете разделить Iterable на значения, используя синтаксис «распаковка»:

Разрушение как значения

a, b = (1, 2)
print(a)
# Prints: 1
print(b)
# Prints: 2

Если вы попытаетесь распаковать больше длины итерации, вы получите сообщение об ошибке:

a, b, c = [1]
# Raises: ValueError: not enough values to unpack (expected 3, got 1)
Python 3.x 3.0

Разрушение как список

Вы можете распаковать список неизвестной длины, используя следующий синтаксис:

head, *tail = [1, 2, 3, 4, 5]

Здесь мы извлекаем первое значение как скаляр, а остальные значения - в виде списка:

print(head)
# Prints: 1
print(tail)
# Prints: [2, 3, 4, 5]

Это эквивалентно:

l = [1, 2, 3, 4, 5]
head = l[0]
tail = l[1:]

Он также работает с несколькими элементами или элементами, составляющими конец списка:

a, b, *other, z = [1, 2, 3, 4, 5]
print(a, b, z, other)
# Prints: 1 2 5 [3, 4]

Игнорирование значений в назначениях деструктурирования

Если вас интересует только данное значение, вы можете использовать _ чтобы указать, что вас это не интересует. Примечание: это все равно будет установлено _ , большинство людей не используют его как переменную.

a, _ = [1, 2]
print(a)
# Prints: 1
a, _, c = (1, 2, 3)
print(a)
# Prints: 1
print(c)
# Prints: 3
Python 3.x 3.0

Игнорирование списков в назначениях деструктурирования

Наконец, вы можете игнорировать многие значения, используя синтаксис *_ в присваивании:

a, *_ = [1, 2, 3, 4, 5]
print(a)
# Prints: 1

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

 a, *_, b = [1, 2, 3, 4, 5]
 print(a, b)
 # Prints: 1 5

или извлечь сразу несколько значений:

 a, _, b, _, c, *_ = [1, 2, 3, 4, 5, 6]
 print(a, b, c)
 # Prints: 1 3 5

Аргументы функции упаковки

В функциях вы можете определить ряд обязательных аргументов:

def fun1(arg1, arg2, arg3): 
    return (arg1,arg2,arg3)

который сделает функцию вызываемой только тогда, когда будут указаны три аргумента:

fun1(1, 2, 3)

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

def fun2(arg1='a', arg2='b', arg3='c'):
    return (arg1,arg2,arg3)

поэтому вы можете вызвать функцию различными способами, например:

fun2(1)              → (1,b,c)
fun2(1, 2)           → (1,2,c)
fun2(arg2=2, arg3=3) → (a,2,3)
...

Но вы также можете использовать синтаксис деструктурирования для упаковки аргументов, поэтому вы можете назначать переменные, используя list или dict .

Упаковка списка аргументов

У вас есть список значений

l = [1,2,3]

Вы можете вызвать функцию со списком значений в качестве аргумента, используя синтаксис * :

fun1(*l)
# Returns: (1,2,3)
fun1(*['w', 't', 'f'])
# Returns: ('w','t','f')

Но если вы не предоставляете список, длина которого соответствует количеству аргументов:

fun1(*['oops'])
# Raises: TypeError: fun1() missing 2 required positional arguments: 'arg2' and 'arg3'

Параметр ключевого слова для упаковки

Теперь вы можете также упаковать аргументы с помощью словаря. Вы можете использовать оператор ** чтобы сообщить Python о распаковке dict качестве значений параметра:

d = {
  'arg1': 1,
  'arg2': 2,
  'arg3': 3
}
fun1(**d)
# Returns: (1, 2, 3)

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

fun1(**{'arg1':1, 'arg2':2})
# Raises: TypeError: fun1() missing 1 required positional argument: 'arg3'
fun1(**{'arg1':1, 'arg2':2, 'arg3':3, 'arg4':4})
# Raises: TypeError: fun1() got an unexpected keyword argument 'arg4'

Для функций, которые имеют необязательные аргументы, вы можете скомпоновать аргументы в качестве словаря:

fun2(**d)
# Returns: (1, 2, 3)

Но там вы можете опустить значения, поскольку они будут заменены значениями по умолчанию:

fun2(**{'arg2': 2})
# Returns: ('a', 2, 'c')

И так же, как и раньше, вы не можете давать дополнительные значения, которые не являются существующими параметрами:

fun2(**{'arg1':1, 'arg2':2, 'arg3':3, 'arg4':4})
# Raises: TypeError: fun2() got an unexpected keyword argument 'arg4'

В реальном мире функции могут иметь как позиционные, так и необязательные аргументы, и они работают одинаково:

def fun3(arg1, arg2='b', arg3='c')
    return (arg1, arg2, arg3)

вы можете вызвать функцию только с помощью итерации:

fun3(*[1])
# Returns: (1, 'b', 'c')
fun3(*[1,2,3])
# Returns: (1, 2, 3)

или просто с помощью словаря:

fun3(**{'arg1':1})
# Returns: (1, 'b', 'c')
fun3(**{'arg1':1, 'arg2':2, 'arg3':3})
# Returns: (1, 2, 3)

или вы можете использовать оба метода в одном и том же вызове:

fun3(*[1,2], **{'arg3':3})
# Returns: (1,2,3)

Помните, что вы не можете предоставить несколько значений для одного и того же аргумента:

fun3(*[1,2], **{'arg2':42, 'arg3':3})
# Raises: TypeError: fun3() got multiple values for argument 'arg2'

Распаковка аргументов функции

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

def fun1(*args, **kwargs):
    print(args, kwargs)

Параметры *args и **kwargs являются специальными параметрами, которые устанавливаются в tuple и dict соответственно:

fun1(1,2,3)
# Prints: (1, 2, 3) {}
fun1(a=1, b=2, c=3)
# Prints: () {'a': 1, 'b': 2, 'c': 3}
fun1('x', 'y', 'z', a=1, b=2, c=3)
# Prints: ('x', 'y', 'z') {'a': 1, 'b': 2, 'c': 3}

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

class MyString(str):
    def __init__(self, *args, **kwarg):
        print('Constructing MyString')
        super(MyString, self).__init__(*args, **kwarg)


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