Существует ли существующая встроенная функция Python, которая назначает две или более переменных и возвращает несколько значений при назначении одного выражения? Например:
гипотетически:
attrs, patterns, weight = [] * 3
такой же как:
attrs, patterns, weight = [], [], []
Лучший существующий синтаксис для этого
attrs, patterns, weight = [[] for i in range(3)]
что на самом деле не улучшение по сравнению с [], [], []
. Это имеет преимущество для сложных выражений, хотя.
Если вам нужна функция, вы столкнетесь с проблемой, заключающейся в том, что функции Python принимают объекты, а не выражения. Функция не может оценивать свои выражения аргумента повторно. Если вы хотите написать функцию, вам нужно заключить выражение в lambda
или что-то в этом роде:
def n_times(constructor, n):
return [constructor() for i in range(n)]
attrs, patterns, weight = n_times(lambda: [], 3)
# or
attrs, patterns, weight = n_times(list, 3)
Есть несколько заманчивых, но неправильных вариантов:
# Mistake
attrs = patterns = weight = []
# Also a mistake
attrs, patterns, weight = [[]]*3
которые присваивают один и тот же список каждой переменной вместо создания отдельных списков, потому что присваивание Python не копирует, а умножение списка не копирует элементы, а только ссылки на элементы.
a = b = c = []
Все переменные независимо установлены на одно и то же значение. (Внимание: тот же изменяемый объект, но это верно для любого множественного присваивания в Python.)
См. Документацию оператора присваивания - target_list "="
несколько target_list "="
.
Оператор присваивания оценивает список выражений [...] и назначает один результирующий объект каждому из целевых списков слева направо.
Это было для меня неожиданностью, когда я впервые попробовал это сделать сразу же! Но это работает так, как вы ожидаете.
Если вы хотите иметь поведение, которое вы пытаетесь иметь, вы можете создать пользовательский объект, который ведет себя как это выражение: var1, var2, var3 = __OBJECT__ * 3
Вот пример:
from collections.abc import Iterable
class Custom:
def __init__(self, initial=[]):
if not isinstance(initial, Iterable):
raise ValueError()
self.initial = initial
self.args = initial
def __mul__(self, args):
self.args = [self.initial[:] for _ in range(args)]
return self.args
def __iter__(self):
for _ in range(len(self.args)):
yield self.initial
def __repr__(self):
return '{}'.format(list(self))
Демо-версия:
$> a, b, c = Custom() * 3
$> print(a, b, c) # [] [] []
$> id(a) == id(b) == id(c) # False
$> a, b, c = Custom(()) * 3
$> print(a, b, c) # () () ()
$> id(a) == id(b) == id(c) # True