When I talked about Python destructuring assignment I also mentioned the * and ** syntax, and referred to it as "operators" which indeed is not right (though it's common to name them like that). They should be better referred as unpacking/packing syntax or star expressions. For the different use cases of this syntax:
- function invokation: f1(*args, **kwargs) or function definition: def f2(*args, **kwargs) we should talk about arguments unpacking or packing
- When used in collection literals we should talk about iterator unpacking: [*items1, *items2] and dictionary unpacking: {**dict1, **dict2}, with the expressions being called "starred expressions"
- When used on the left side of an assignment: first, *reminder = my_list, we talk of a "starred target".
As we know the unpacking (destructuring) happens automatically when performing a multiple assignment, with no need of using * at all
x, y = [1, 2]
print(f"x: {x}, y: {y}")
# x: 1, y: 2
There are some advanced uses that I tend to forget. We can use multiple assignment with object attributes or dictionary keys:
@dataclass
class Person:
name: str
age: int
country: str
# multiple assignment to attributes of an object
p1 = Person("Antoine", 47, "France")
p1.name, p1.age = ["Francois", 48]
print(f"p1.name: {p1.name}, p1.age: {p1.age}")
# multiple assignment to dictionary keys
d1 = {}
d1["name"], d1["age"] = ["Francois", 48]
print(f"d1['name']: {d1['name']}, d1['age']: {d1['age']}")
As I explained in this post we can unpack nested structures:
x, [a, b], y = [1, [2, 3], 4]
print(f"x: {x}, a: {a}, b: {b}, y: {y}")
# x: 1, a: 2, b: 3, y: 4
But notice that nested unpacking works for assignment, but not for function parameters. Surprisingly this is something that worked in Python2 but was lost in Python3.
>>> def f(a, (b, c)):
... return c
SyntaxError: Function parameters cannot be parenthesized
>>> def f(a, [b, c]):
... return c
...
SyntaxError: invalid syntax
Python is missing the object destructuring assignment feature present JavaScript, I mean:
const user = {
id: 42,
isVerified: true,
};
const { id, isVerified } = user;
So we have to use this more verbose approach (notice that itemgetter and attrgetter are a nice option for dynamic scenarios)
p1 = Person("Antoine", 47, "France")
name, country = p1.name, p1.country
name, country = attrgetter("name", "country")(p1)
name, age = d1["name"], d1["age"]
name, age = itemgetter("name", "age")(d1)
No comments:
Post a Comment