Destructuring dicts and objects in Python
In Javascript, I can use destructuring to extract properties I want from a javascript objects in one liner. For example:
currentUser = {
"id": 24,
"name": "John Doe",
"website": "http://mywebsite.com",
"description": "I am an actor",
"email": "[email protected]",
"gender": "M",
"phone_number": "+12345678",
"username": "johndoe",
"birth_date": "1991-02-23",
"followers": 46263,
"following": 345,
"like": 204,
"comments": 9
}
let { id, username } = this.currentUser;
console.log(id) // 24
console.log(username) //johndoe
Do we have something similar in Python for Python dicts and Python objects? Example of Python way of doing for python objects:
class User:
def __init__(self, id, name, website, description, email, gender, phone_number, username):
self.id = id
self.name = name
self.website = website
self.description = description
self.email = email
self.gender = gender
self.phone_number = phone_number
self.username = username
current_user = User(24, "Jon Doe", "http://mywebsite.com", "I am an actor", "[email protected]", "M", "+12345678", "johndoe")
# This is a pain
id = current_user.id
email = current_user.email
gender = current_user.gender
username = current_user.username
print(id, email, gender, username)
Writing those 4 lines (as mentioned in example above) vs writing a single line (as mentioned below) to fetch values I need from an object is a real pain point.
(id, email, gender, username) = current_user
Solution 1:
You can use operator
module from standard library as follows:
from operator import attrgetter
id, email, gender, username = attrgetter('id', 'email', 'gender', 'username')(current_user)
print(id, email, gender, username)
In case you have a dict like from your example
currentUser = {
"id": 24,
"name": "John Doe",
"website": "http://mywebsite.com",
"description": "I am an actor",
"email": "[email protected]",
"gender": "M",
"phone_number": "+12345678",
"username": "johndoe",
"birth_date": "1991-02-23",
"followers": 46263,
"following": 345,
"like": 204,
"comments": 9
}
just use itemgetter
instead of attrgetter
:
from operator import itemgetter
id, email, gender, username = itemgetter('id', 'email', 'gender', 'username')(currentUser)
print(id, email, gender, username)
Solution 2:
Building off of other answers, I would recommend also using Python's dataclasses
and use __getitem__
to get specific fields:
from dataclasses import astuple, dataclass
@dataclass
class User:
id: int
name: str
website: str
description: str
email: str
gender: str
phone_number: str
username: str
def __iter__(self):
return iter(astuple(self))
def __getitem__(self, keys):
return iter(getattr(self, k) for k in keys)
current_user = User(id=24, name="Jon Doe", website="http://mywebsite.com", description="I am an actor", email="[email protected]", gender="M", phone_number="+12345678", username="johndoe")
# Access fields sequentially:
id, _, email, *_ = current_user
# Access fields out of order:
id, email, gender, username = current_user["id", "email", "gender", "username"]