Required Fields vs Defaults
Understanding required fields, default values, and default_factory for mutable defaults.
How does Pydantic decide if a field is required or optional? Is it just whether I give it a default value?
Exactly. If a field has no default value, it's required — you must provide it when creating the model. If it has a default, it's optional:
from pydantic import BaseModel
class Config(BaseModel):
host: str # required — no default
port: int = 8080 # optional — defaults to 8080
debug: bool = False # optional — defaults to False
# Only host is required
c = Config(host="localhost")
print(c.port) # 8080
print(c.debug) # False
Required fields must come before optional fields in the class definition. Python won't let you put a field without a default after one that has one — same rule as function arguments.
What if my default is a mutable thing like a list? I've heard that's dangerous in regular Python.
Great instinct. In regular Python, a mutable default is shared across all instances — a classic trap. Pydantic handles simple cases like list[str] = [] safely by copying the default. But for anything more complex, use default_factory:
from pydantic import BaseModel, Field
class Pipeline(BaseModel):
name: str
steps: list[str] = Field(default_factory=list)
config: dict[str, str] = Field(default_factory=dict)
default_factory=list means "call list() to create a fresh empty list for each new instance." No shared state, no surprises.
When would I use default_factory instead of just = []?
For simple defaults like = [] or = {}, Pydantic copies them safely, so either approach works. Use default_factory when your default is expensive to compute or when you want to be explicit about creating a new object each time:
from datetime import datetime
class Event(BaseModel):
title: str
created_at: datetime = Field(default_factory=datetime.now)
attendees: list[str] = Field(default_factory=list)
e1 = Event(title="Launch")
print(e1.created_at) # current timestamp
print(e1.attendees) # []
The default_factory=datetime.now is evaluated at creation time — each Event gets its own timestamp.
Can I mix required and optional fields freely as long as required ones come first?
Yes. The pattern is: all required fields first, then all fields with defaults. Pydantic follows Python's rules here:
class Order(BaseModel):
# Required
customer_id: str
items: list[str]
# Optional (with defaults)
status: str = "pending"
notes: str = ""
priority: int = 0
order = Order(customer_id="C123", items=["widget", "gadget"])
print(order.status) # "pending"
print(order.priority) # 0
This is a pattern you'll use in every model — required fields define what must be provided, defaults define sensible fallbacks.
Practice your skills
Sign up to write and run code in this lesson.
Required Fields vs Defaults
Understanding required fields, default values, and default_factory for mutable defaults.
How does Pydantic decide if a field is required or optional? Is it just whether I give it a default value?
Exactly. If a field has no default value, it's required — you must provide it when creating the model. If it has a default, it's optional:
from pydantic import BaseModel
class Config(BaseModel):
host: str # required — no default
port: int = 8080 # optional — defaults to 8080
debug: bool = False # optional — defaults to False
# Only host is required
c = Config(host="localhost")
print(c.port) # 8080
print(c.debug) # False
Required fields must come before optional fields in the class definition. Python won't let you put a field without a default after one that has one — same rule as function arguments.
What if my default is a mutable thing like a list? I've heard that's dangerous in regular Python.
Great instinct. In regular Python, a mutable default is shared across all instances — a classic trap. Pydantic handles simple cases like list[str] = [] safely by copying the default. But for anything more complex, use default_factory:
from pydantic import BaseModel, Field
class Pipeline(BaseModel):
name: str
steps: list[str] = Field(default_factory=list)
config: dict[str, str] = Field(default_factory=dict)
default_factory=list means "call list() to create a fresh empty list for each new instance." No shared state, no surprises.
When would I use default_factory instead of just = []?
For simple defaults like = [] or = {}, Pydantic copies them safely, so either approach works. Use default_factory when your default is expensive to compute or when you want to be explicit about creating a new object each time:
from datetime import datetime
class Event(BaseModel):
title: str
created_at: datetime = Field(default_factory=datetime.now)
attendees: list[str] = Field(default_factory=list)
e1 = Event(title="Launch")
print(e1.created_at) # current timestamp
print(e1.attendees) # []
The default_factory=datetime.now is evaluated at creation time — each Event gets its own timestamp.
Can I mix required and optional fields freely as long as required ones come first?
Yes. The pattern is: all required fields first, then all fields with defaults. Pydantic follows Python's rules here:
class Order(BaseModel):
# Required
customer_id: str
items: list[str]
# Optional (with defaults)
status: str = "pending"
notes: str = ""
priority: int = 0
order = Order(customer_id="C123", items=["widget", "gadget"])
print(order.status) # "pending"
print(order.priority) # 0
This is a pattern you'll use in every model — required fields define what must be provided, defaults define sensible fallbacks.
Practice your skills
Sign up to write and run code in this lesson.