Reputation:
Is there an existing Python builtin function which assigns two or more variables and returns multiple values upon assigning a single expression? For example:
hypothetically:
attrs, patterns, weight = [] * 3
is the same as:
attrs, patterns, weight = [], [], []
Upvotes: 1
Views: 67
Reputation: 485
a = b = c = []
All variables are independently set to the same value. (Caution: the same mutable object, but that is true of any multiple assignment in Python.)
See the documentation of the assignment statement - multiple target_list "="
sections are allowed.
An assignment statement evaluates the expression list [...] and assigns the single resulting object to each of the target lists, from left to right.
This was a surprise to me when I first tried it in an immediate session! But it works just as you'd expect.
Upvotes: 0
Reputation: 9267
If you want to have the behaviour you're trying to have, you can create a custom object that behaves like this expression: var1, var2, var3 = __OBJECT__ * 3
Here is an example:
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))
Demo:
$> 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
Upvotes: 0
Reputation: 281748
The best existing syntax for that is
attrs, patterns, weight = [[] for i in range(3)]
which isn't really an improvement over [], [], []
. It has an advantage for complex expressions, though.
If you wanted a function, you'd run into the problem that Python functions take objects, not expressions. A function can't evaluate its argument expressions repeatedly. If you wanted to write a function, you'd have to wrap the expression in a lambda
or something:
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)
There are a few tempting but wrong options:
# Mistake
attrs = patterns = weight = []
# Also a mistake
attrs, patterns, weight = [[]]*3
which assign the same list to each variable instead of making separate lists, because Python assignment doesn't make copies, and list multiplication doesn't copy the elements, only references to the elements.
Upvotes: 2