Types & Automatic Validation
Using str, int, float, bool, Optional, and list types with Pydantic's automatic validation.
I know Pydantic checks types, but what types can I actually use? Just the basic Python ones?
You can use all the built-in Python types — str, int, float, bool — plus types from the typing module. Pydantic understands them all and validates accordingly:
from pydantic import BaseModel
from typing import Optional
class Sensor(BaseModel):
name: str
value: float
is_active: bool
unit: Optional[str] = None
Each type tells Pydantic what to expect. float means numeric, bool means true/false, and Optional[str] means "a string or None".
What does Optional actually do? Is it different from just setting a default?
Optional[str] means the field can be str or None. Combined with a default of None, it makes the field truly optional — you don't have to provide it at all:
# Both work
s1 = Sensor(name="temp", value=22.5, is_active=True, unit="celsius")
s2 = Sensor(name="temp", value=22.5, is_active=True) # unit defaults to None
print(s2.unit) # None
Without Optional, the field is required and must be the declared type. With Optional[str] = None, you're saying "this can be a string, or it can be missing entirely."
What about lists? Can I have a field that's a list of integers?
Absolutely. Use list[int] (or List[int] from typing in older Python). Pydantic validates every element in the list:
class Measurement(BaseModel):
label: str
readings: list[float]
tags: list[str] = []
m = Measurement(label="pressure", readings=[1.0, 1.5, 2.3])
print(m.readings) # [1.0, 1.5, 2.3]
If any element in readings can't be converted to a float, Pydantic raises an error for that specific element. It tells you exactly which index failed.
What about coercion? I remember that Pydantic converts "30" to 30 for integers. Does it do that for booleans too?
Yes, but be careful. Pydantic's coercion follows sensible rules:
| Input | int field | float field | bool field |
|---|---|---|---|
"42" | 42 | 42.0 | error |
42 | 42 | 42.0 | error |
True | 1 | 1.0 | True |
0 | 0 | 0.0 | error |
In Pydantic v2's default strict-ish mode for booleans, only actual True/False values are accepted for bool fields. Numbers and strings like "yes" won't silently become True. This prevents the kind of subtle bugs where 0 becomes False and breaks your logic.
So the type annotations are actually enforced, not just hints like in regular Python?
Exactly. In plain Python, type hints are suggestions — the interpreter ignores them. In Pydantic, they're contracts. Declare age: int and Pydantic guarantees it will be an int by the time you use it. That's the whole point.
Practice your skills
Sign up to write and run code in this lesson.
Types & Automatic Validation
Using str, int, float, bool, Optional, and list types with Pydantic's automatic validation.
I know Pydantic checks types, but what types can I actually use? Just the basic Python ones?
You can use all the built-in Python types — str, int, float, bool — plus types from the typing module. Pydantic understands them all and validates accordingly:
from pydantic import BaseModel
from typing import Optional
class Sensor(BaseModel):
name: str
value: float
is_active: bool
unit: Optional[str] = None
Each type tells Pydantic what to expect. float means numeric, bool means true/false, and Optional[str] means "a string or None".
What does Optional actually do? Is it different from just setting a default?
Optional[str] means the field can be str or None. Combined with a default of None, it makes the field truly optional — you don't have to provide it at all:
# Both work
s1 = Sensor(name="temp", value=22.5, is_active=True, unit="celsius")
s2 = Sensor(name="temp", value=22.5, is_active=True) # unit defaults to None
print(s2.unit) # None
Without Optional, the field is required and must be the declared type. With Optional[str] = None, you're saying "this can be a string, or it can be missing entirely."
What about lists? Can I have a field that's a list of integers?
Absolutely. Use list[int] (or List[int] from typing in older Python). Pydantic validates every element in the list:
class Measurement(BaseModel):
label: str
readings: list[float]
tags: list[str] = []
m = Measurement(label="pressure", readings=[1.0, 1.5, 2.3])
print(m.readings) # [1.0, 1.5, 2.3]
If any element in readings can't be converted to a float, Pydantic raises an error for that specific element. It tells you exactly which index failed.
What about coercion? I remember that Pydantic converts "30" to 30 for integers. Does it do that for booleans too?
Yes, but be careful. Pydantic's coercion follows sensible rules:
| Input | int field | float field | bool field |
|---|---|---|---|
"42" | 42 | 42.0 | error |
42 | 42 | 42.0 | error |
True | 1 | 1.0 | True |
0 | 0 | 0.0 | error |
In Pydantic v2's default strict-ish mode for booleans, only actual True/False values are accepted for bool fields. Numbers and strings like "yes" won't silently become True. This prevents the kind of subtle bugs where 0 becomes False and breaks your logic.
So the type annotations are actually enforced, not just hints like in regular Python?
Exactly. In plain Python, type hints are suggestions — the interpreter ignores them. In Pydantic, they're contracts. Declare age: int and Pydantic guarantees it will be an int by the time you use it. That's the whole point.
Practice your skills
Sign up to write and run code in this lesson.