A Pythonista's ways of data unpacking.
To index or to unpack, that is the question. During a code review, I came across unpleasant-looking code. For me, coding is an art. It tells stories about us. I love beautiful, creative and artistic stories. Thus, I love beautiful and creative code.
Back to the code review. The unpleasant "looking" code emerged from an index accessing of data.
# task A: get jack and the rest
friends_data = ["jane", "john", "jill", "jack", ]
# the usual indexing
jack = friends_data[-1] # -1 the last element in data | data[3] index 3, 4th element
rest = friends_data[:-1] # all but the last element
print(f"👋 hello, {jack!r} out of the {rest=}!")
# "👋 hello, 'jack' out of the rest=['jane', 'john', 'jill']!"
As data become more complex, unpleasant-looking index accessing emerges.
# task B: get jack and his value (23)
data = [("jane", 21), ("john", 32), ("jill", 45), ("jack", 23), ]
# the usual indexing
jack = data[-1][0]
jacks_value[-1][1]
print(f"This is {jack!r} with the value {jacks_value}!")
# "This is 'jack' with the value 23!"
A prettier solution could be pattern matching. For example in Rust 🦀, we could perform destructuring assignments with match.
// task A: get jack and the rest
// unpacking/destructuring assignment
fn main() {
let friends_data = ["jane", "john", "jill", "jack", ];
let data = [("jane", 21), ("john", 32), ("jill", 45), ("jack", 23),];
match friends_data {
[.., jack] =>
println!("👋 Hey, rust, this is {jack}!"),
}
match data {
[.., (jack, jacks_value)] =>
println!("Oh, rust, this is {jack} with the values {jacks_value}!")
}
}
// cargo run
// >> 👋 Hey, rust, this is jack!
// >> Oh, rust, this is jack with the values 23!
Python 🐍 offers destructuring assignments too. It brings beauty back to data accessing.
# task A: get jack and the rest
*rest, jack = friends_data
print(f"👋 hello, {jack!r} out of the {rest=}!")
# "👋 hello, 'jack' out of the rest=['jane', 'john', 'jill']!"
# task B: get jack and his value (23)
*_, (jack, jacks_value) = data # *_ since we dont need the rest we throw them away
print(f"This is {jack!r} with the value {jacks_value}!")
# "This is 'jack' with the value 23!"
It's even prettier when you unpack nested weird data.
weird_data = [("jack", 23),]
[(jack, jacks_value), ] = weird_data
print(f"This is still {jack!r} with the value {jacks_value}!")
# "This is still 'jack' with the value 23!"
To index or to unpack? I hope the answer is less unclear. Until then, keep on unpacking ...
Top comments (0)