Sample 2,769 Python functions from the Opus 4.7 corpus. Count how many have -> SomeType in the signature.
Result: 84.3% of them do.
What this means
Python type hints (PEP 484) are optional. In the general Python ecosystem:
- Django / Flask codebases: ~30-40% type-annotated (historical estimates)
- Libraries like FastAPI, Pydantic: ~70%+ (type hints are core to how they work)
- Corporate Python (internal tools, scripts): often <20%
- AI-generated Python (generic): varies wildly
Opus 4.7 averages 84.3% — meaningfully above most human-written Python.
Why so high
1. FastAPI is the default web framework
FastAPI requires type hints to work. 225 FastAPI repos in the corpus push the typed-return rate up dramatically. A single FastAPI endpoint like:
async def get_user(user_id: int, db: Session = Depends(get_db)) -> UserSchema:
...
Has 3 type annotations in 2 lines. Multiply across thousands of endpoints and the stat swells.
2. from __future__ import annotations is standard
14,070 imports of __future__ — often with annotations. This future-flag makes all annotations lazy-evaluated, eliminating circular-import pain. Its presence correlates with projects that want to type everything.
3. Pydantic permeates the corpus
3,342 uses of pydantic. Pydantic models are always fully typed. When a codebase uses Pydantic, adjacent code (validators, converters, route handlers) gravitates toward being typed too.
4. typing is the #3 Python import
Across all Opus 4.7 Python files, typing appears 20,368 times — behind only __future__ (19,906) and os (16,469). Explicit imports of typing.Optional, typing.Union, typing.List etc. happen constantly.
What 84% typed looks like in practice
Reading a sample of Opus 4.7 Python, you see:
from typing import Any, Optional
from datetime import datetime
from pydantic import BaseModel
class UserProfile(BaseModel):
id: int
name: str
email: str
created_at: datetime
metadata: Optional[dict[str, Any]] = None
def serialize_user(user: UserProfile) -> dict[str, Any]:
return user.model_dump()
async def fetch_active_users(limit: int = 100) -> list[UserProfile]:
...
Every function signature, every return, every parameter — typed.
The 16% that don’t
Looking at untyped Python in the corpus:
- Data-science scripts (
analysis.py,notebook_export.py) — pandas-heavy code where return types are hard to express - Legacy patterns in older Python repos
- Simple CLI entry points where types add noise without benefit
- Test fixtures (pytest fixtures often omit return types by convention)
So the 16% untyped isn’t neglect; it’s often reasonable practice for specific file roles.
Implications
For training a Python code model
If you’re fine-tuning on this corpus, your model will learn to write typed Python by default. That’s a desirable property. But it also means your model will produce type-hint-heavy output even in contexts where humans would omit them (quick scripts, REPL-style code).
You may want to mix in untyped Python samples to keep the model flexible.
For Python tooling
If your linter, formatter, or analyzer assumes “most Python is untyped,” it’ll be wrong in the Opus 4.7 era. Strict mypy is a reasonable default rule to enable on Opus 4.7 repos.
For static analysis
The 84% typing rate means you can run mypy --strict on most Opus 4.7 Python code and get useful signal. Low false-positive rate because the annotations are real.
Comparison: TypeScript vs Python
| Language | Typing discipline in Opus 4.7 |
|---|---|
| TypeScript | 100% of repos have tsconfig.json |
| Python | 84% of function signatures have -> return_type |
TypeScript is structurally typed (no way to write untyped TS in strict mode). Python is optionally typed, and Opus 4.7 chose to type most of it anyway.
Takeaway
If you associate AI-generated Python with loosely-typed scripts, the data says otherwise. Opus 4.7’s Python is Pydantic + FastAPI + typing everywhere, hitting mypy-strict standards more often than not.
The model doesn’t just generate syntactically correct Python — it generates typed Python.
Related: Every Opus 4.7 TypeScript Repo Is Typed.