
Understanding the **
Unpacking Operator in Python
The **
operator in Python is known as the dictionary unpacking operator. It allows you to expand a dictionary into named arguments when calling a function or creating an object. It's especially useful when you're working with functions or constructors that take many keyword arguments.
Basic Example
Suppose you have a function that takes several keyword arguments:
def greet(name, age, city):
print(f"Hello, my name is {name}, I'm {age} years old and I live in {city}.")
Now you can call it like this:
data = {
"name": "Alice",
"age": 30,
"city": "New York"
}
greet(**data)
Behind the Scenes
The call greet(**data)
is equivalent to:
greet(name="Alice", age=30, city="New York")
Using **
with Classes
You can also use **
to pass dictionary data to a class constructor:
class User:
def __init__(self, id, name, email, role):
self.id = id
self.name = name
self.email = email
self.role = role
data = {
"id": "123",
"name": "Juan Pérez",
"email": "juan@example.com",
"role": "READ"
}
user = User(**data)
Real-World Usage: FastAPI or Pydantic Models
With libraries like Pydantic, it's common to use **
to construct new models based on the output of methods like .model_dump()
:
class UserOut(BaseModel):
id: str
name: str
email: str
role: str
PK: str
class User(BaseModel):
id: str
name: str
email: str
role: str
def to_db_model(self):
return UserOut(PK=f"user#{self.id}", **self.model_dump())
Why Use **
?
- Cleaner code: Avoids manually passing each attribute
- Maintainability: Adding new fields automatically updates the constructor call
- Flexibility: Easily integrate dynamic data structures
Pro Tip: You can combine regular keyword arguments with
**
unpacking:create_user(role="ADMIN", **user_data)