Значение по умолчанию в распаковке Python
Есть ли способ получить значение по умолчанию, если количество распаковываемых значений слишком мало по сравнению со списком переменных?
Например:
a, b, c = read_json(request)
Это работает, если read_json
возвращает массив из трех или более переменных. Если он возвращает только два, я получаю исключение при назначении c
, Итак, есть ли способ установить c
к значению по умолчанию, если его нельзя распаковать правильно? Что-то вроде:
a, b, (c=2) = read_json(request)
Что похоже на то, что вы делаете при определении функции с аргументами по умолчанию.
Спасибо!
5 ответов
Вы могли бы попробовать *
распаковка с последующей обработкой:
a, b, *c = read_json(request)
c = c[0] if c else 2
Это назначит a
а также b
как обычно. Если c
назначено что-то, это будет list
с одним элементом. Если были распакованы только два значения, оно будет пустым list
, Второе утверждение присваивает c
его первый элемент, если он есть, или значение по умолчанию 2
иначе.
>>> a, b, *c = 1, 2, 3
>>> c = c[0] if c else 2
>>> a
1
>>> b
2
>>> c
3
>>> a, b, *c = 1, 2
>>> c = c[0] if c else 2
>>> a
1
>>> b
2
>>> c
2
Вы можете использовать цепную функцию из itertools, которая является частью стандартной библиотеки Python. Он служит заполнителем по умолчанию в случае, если в первом списке нет значений. Переменная списка 'defaults' в моем примере может иметь количество различных значений для каждой распаковываемой переменной (в примере у меня значение по умолчанию для всех трех значений равно 0).
from itertools import chain
defaults = [0] * 3
data = []
a, b, c, *_ = chain(data, defaults)
print(a, b, c)
data.append(1)
a, b, c, *_ = chain(data, defaults)
print(a, b, c)
data.append(2)
a, b, c, *_ = chain(data, defaults)
print(a, b, c)
data.append(3)
a, b, c, *_ = chain(data, defaults)
print(a, b, c)
data.append(4)
a, b, c, *_ = chain(data, defaults)
print(a, b, c)
Выходы:
0 0 0
1 0 0
1 2 0
1 2 3
1 2 3
Если вам нужно однострочное решение, сработает следующий трюк с использованием параметров по умолчанию в лямбда-функциях, но он несколько сбивает с толку и его трудно читать:
a, b, c = (lambda a, b, c=3: (a, b, c))(*(1, 2))
print(a, b, c)
a, b, c = (lambda a, b, c=3: (a, b, c))(*(1, 2, 4))
print(a, b, c)
Выход:
1 2 3
1 2 4
В ответ на вопрос нет, вы не можете сделать это.
Кроме того, я бы рекомендовал не возвращать различное количество аргументов из функций - это вызовет только дальнейшие проблемы с компиляциями (в данном случае речь идет об этом). Каждый раз, когда вы вызываете эту функцию, вам нужно будет проверить, были ли возвращены 2 или 3 значения. (Распаковка может быть полезна здесь, но вам все равно нужно будет проверить эти возвращаемые переменные). например:
a, b, *others = read_json(request)
if others:
c = others[0]
Было бы разумнее, если бы считал, что read_json - ваша функция, если функция может вернуть dict с установленными значениями по умолчанию:
def read_json(request):
ret = { 'c': 2 }
# ... set 'a' and 'b' and 'c' if possible
return ret
res = read_json(request)
c = res['c']
Я знаю, что опаздываю, но об этом стоит упомянуть.
если все значения по умолчанию, которые вам нужны, одинаковы, вы можете использовать этот ловкий трюк:
def return_tuple():
return (1, 2)
def return_list():
return [1, 2]
a, b, c = return_tuple() + (0,)
print(a, b, c)
# 1 2 0
a, b, c = return_list() + [0]
print(a, b, c)
# 1 2 0
a, b, c, d = return_list() + [0, 0]
print(a, b, c, d)
вы можете иметь значения по умолчанию для других типов:
a, b, c, d = list(range(1, 3)) + [0, 0]
print(a, b, c, d)
Однако, если значения по умолчанию не совпадают, есть еще одна хитрость:
defaults = [10, 11, 12, 13]
result = [1, 2]
a, b, c, d = result + defaults[len(result):]
print(a, b, c, d)
# 1, 2, 12, 13
# other types
result = range(2)
a, b, c, d = list(result) + defaults[len(result):]
print(a, b, c, d)
# 0 1 12 13
надеюсь, кто-то еще сочтет это полезным