惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Secure Thoughts
Recent Commits to openclaw:main
Recent Commits to openclaw:main
H
Heimdal Security Blog
SecWiki News
SecWiki News
H
Hacker News: Front Page
N
News | PayPal Newsroom
L
LINUX DO - 最新话题
N
News and Events Feed by Topic
TaoSecurity Blog
TaoSecurity Blog
AI
AI
C
Cybersecurity and Infrastructure Security Agency CISA
Scott Helme
Scott Helme
PCI Perspectives
PCI Perspectives
S
Securelist
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Cyberwarzone
Cyberwarzone
A
Arctic Wolf
Forbes - Security
Forbes - Security
T
Tor Project blog
Spread Privacy
Spread Privacy
WordPress大学
WordPress大学
I
Intezer
Martin Fowler
Martin Fowler
Help Net Security
Help Net Security
P
Proofpoint News Feed
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Cisco Talos Blog
Cisco Talos Blog
Latest news
Latest news
博客园 - 司徒正美
W
WeLiveSecurity
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
V
V2EX
P
Palo Alto Networks Blog
Google DeepMind News
Google DeepMind News
IT之家
IT之家
阮一峰的网络日志
阮一峰的网络日志
V
Vulnerabilities – Threatpost
Jina AI
Jina AI
S
Security Affairs
Hacker News - Newest:
Hacker News - Newest: "LLM"
Simon Willison's Weblog
Simon Willison's Weblog
Project Zero
Project Zero
T
Threatpost
P
Privacy International News Feed
人人都是产品经理
人人都是产品经理
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Application and Cybersecurity Blog
Application and Cybersecurity Blog
博客园 - Franky
Hugging Face - Blog
Hugging Face - Blog
Apple Machine Learning Research
Apple Machine Learning Research

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
Python Metaclasses, What's Actually Happening When You Write class
shayan holak · 2026-04-29 · via DEV Community

Every Python developer knows that everything is an object. What fewer know is that classes are objects too, and like every other object, they are instances of something. That something is a metaclass. Understanding metaclasses means understanding how Python builds classes in the first place, which turns out to explain a lot of behavior that otherwise looks like magic.

Classes Are Instances of type

Start here:

class MyClass:
    pass

print(type(MyClass))    # <class 'type'>
print(type(int))        # <class 'type'>
print(type(str))        # <class 'type'>
print(type(type))       # <class 'type'>

Enter fullscreen mode Exit fullscreen mode

type is the metaclass of every class you have ever written unless you said otherwise. It is the class of classes. It is also an instance of itself, which is one of those things that is true and also slightly uncomfortable to think about for too long.

Since type is a class, you can call it to create new classes at runtime. The three-argument form of type does exactly this:

# type(name, bases, namespace)
MyClass = type("MyClass", (object,), {"x": 42, "greet": lambda self: "hello"})

obj = MyClass()
print(obj.x)        # 42
print(obj.greet())  # hello

Enter fullscreen mode Exit fullscreen mode

This is not a trick or an edge case. This is literally what happens when Python processes a class statement. The class syntax is a shorthand for calling type (or a custom metaclass) with the class name, base classes, and namespace.

The Class Creation Protocol, Step by Step

When Python encounters a class block, it does not just evaluate the body and hand it to type. It follows a specific protocol.

Step 1: Determine the metaclass.

Python looks for a metaclass keyword argument in the class definition. If not found, it checks the base classes for their metaclass. If no bases specify one, it defaults to type.

class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

print(type(MyClass))  # <class '__main__.Meta'>

Enter fullscreen mode Exit fullscreen mode

Step 2: Prepare the namespace.

Python calls metaclass.__prepare__(name, bases, **kwargs). This returns the dictionary that will be used as the class namespace while the body executes. By default it returns a plain dict, but you can return an OrderedDict or a custom mapping to do things like track definition order or intercept attribute assignments.

class OrderedMeta(type):
    @classmethod
    def __prepare__(mcs, name, bases, **kwargs):
        return {}  # default, but you can return anything dict-like

Enter fullscreen mode Exit fullscreen mode

Step 3: Execute the class body.

The class body runs as a function, with the namespace from step 2 as its local scope. Every name defined in the body becomes a key in that namespace. This is why you can do things like:

class MyClass:
    items = []
    for i in range(3):
        items.append(i)  # this runs at class definition time

Enter fullscreen mode Exit fullscreen mode

Step 4: Call the metaclass.

Python calls metaclass(name, bases, namespace) with the populated namespace. This is where the class object is actually created. This is type.__call__, which internally calls type.__new__ to create the class object and type.__init__ to initialize it.

The full chain: Meta(name, bases, ns)Meta.__call__Meta.__new__ + Meta.__init__.

Writing a Metaclass That Does Something Useful

The canonical example of a metaclass that earns its complexity is one that enforces an interface. Suppose you want an abstract base pattern without the abc module, where subclasses that forget to implement required methods fail at class definition time rather than at instantiation.

class RequiredMethodsMeta(type):
    required = []

    def __new__(mcs, name, bases, namespace):
        cls = super().__new__(mcs, name, bases, namespace)

        # skip the check for the base class itself
        if bases:
            missing = [
                method for method in mcs.required
                if method not in namespace
            ]
            if missing:
                raise TypeError(
                    f"{name} must implement: {', '.join(missing)}"
                )
        return cls


class Shape(metaclass=RequiredMethodsMeta):
    RequiredMethodsMeta.required = ["area", "perimeter"]


class Circle(Shape):
    def area(self):
        return 3.14 * self.radius ** 2

    def perimeter(self):
        return 2 * 3.14 * self.radius

# This class raises TypeError at definition time, not at use time
class Square(Shape):
    def area(self):
        return self.side ** 2
    # missing perimeter
# => TypeError: Square must implement: perimeter

Enter fullscreen mode Exit fullscreen mode

The error happens when the class statement for Square is processed, before any instance is ever created. This is the key advantage of metaclass-level enforcement over runtime checks.

new vs init in a Metaclass

When you subclass type, the two methods you override are __new__ and __init__. The distinction matters.

__new__ creates and returns the class object. This is where you modify the class before it exists as a complete object. You can alter the namespace, add or remove attributes, change the bases. The class has not been fully constructed yet.

__init__ receives the already-created class object and can perform post-construction setup. The class exists at this point but has not been returned to the caller yet.

class TrackedMeta(type):
    registry = []

    def __new__(mcs, name, bases, namespace):
        # Modify namespace before class is created
        namespace["_created_by"] = "TrackedMeta"
        cls = super().__new__(mcs, name, bases, namespace)
        return cls

    def __init__(cls, name, bases, namespace):
        # Class exists, register it
        TrackedMeta.registry.append(cls)
        super().__init__(name, bases, namespace)


class Base(metaclass=TrackedMeta):
    pass

class Child(Base):
    pass

print(TrackedMeta.registry)  # [<class 'Base'>, <class 'Child'>]
print(Base._created_by)      # TrackedMeta

Enter fullscreen mode Exit fullscreen mode

The practical rule: use __new__ when you need to alter what the class is. Use __init__ when you just need to register or observe it after it is created.

prepare and Definition Order

__prepare__ is underused and often the cleaner solution to problems people solve with __new__. Because it controls the namespace used during class body execution, it can observe the order in which things are defined.

A plain dict preserves insertion order in Python 3.7+, so you get definition order for free now. But __prepare__ lets you go further: you can use a custom mapping that intercepts assignments, rejects duplicates, or transforms values as they are added.

class NoDuplicatesMeta(type):
    @classmethod
    def __prepare__(mcs, name, bases, **kwargs):
        return NoDuplicatesDict()

    def __new__(mcs, name, bases, namespace):
        return super().__new__(mcs, name, bases, dict(namespace))


class NoDuplicatesDict(dict):
    def __setitem__(self, key, value):
        if key in self and not key.startswith("_"):
            raise TypeError(f"Duplicate attribute: {key}")
        super().__setitem__(key, value)


class MyClass(metaclass=NoDuplicatesMeta):
    x = 1
    y = 2
    x = 3  # raises TypeError: Duplicate attribute: x

Enter fullscreen mode Exit fullscreen mode

This catches the duplicate at class body execution time, not after. The error message points at the right place.

Metaclass Conflict and the MRO Problem

If you use multiple inheritance and the base classes have different metaclasses, Python raises a TypeError unless one metaclass is a subclass of all the others.

class MetaA(type): pass
class MetaB(type): pass

class A(metaclass=MetaA): pass
class B(metaclass=MetaB): pass

class C(A, B): pass
# TypeError: metaclass conflict: the metaclass of a derived class
# must be a subclass of the metaclasses of all its bases

Enter fullscreen mode Exit fullscreen mode

The fix is to create a combined metaclass that inherits from both:

class MetaC(MetaA, MetaB): pass

class C(A, B, metaclass=MetaC): pass  # works

Enter fullscreen mode Exit fullscreen mode

In practice, metaclass conflicts are a strong signal that the design has gotten complicated. If you are writing three metaclasses that need to be composed, consider whether __init_subclass__ or a class decorator solves the same problem more simply.

init_subclass: The Metaclass You Did Not Have to Write

Python 3.6 added __init_subclass__, which handles the most common metaclass use case without requiring a metaclass at all. It is called on the base class whenever a subclass is created.

class Plugin:
    _registry = {}

    def __init_subclass__(cls, plugin_name=None, **kwargs):
        super().__init_subclass__(**kwargs)
        if plugin_name:
            Plugin._registry[plugin_name] = cls


class JSONPlugin(Plugin, plugin_name="json"):
    def process(self, data): ...

class XMLPlugin(Plugin, plugin_name="xml"):
    def process(self, data): ...

print(Plugin._registry)
# {'json': <class 'JSONPlugin'>, 'xml': <class 'XMLPlugin'>}

Enter fullscreen mode Exit fullscreen mode

No metaclass, no __new__, no type subclass. __init_subclass__ is called automatically at class creation time with whatever keyword arguments were passed in the class definition. For registration patterns, interface enforcement, and configuration at definition time, this handles most cases cleanly.

When a Metaclass Is Actually the Right Tool

Metaclasses are the right tool in a narrow set of situations. They make sense when you need to transform or validate the class namespace before the class object exists, when you need behavior that __init_subclass__ cannot express because it does not run at all for the base class itself, and when you are building framework infrastructure that other developers will subclass without knowing the mechanics.

Django's ORM uses metaclasses. SQLAlchemy uses metaclasses. The abc module uses a metaclass. These are all framework-level concerns where the metaclass is invisible to the end user.

If you are writing application code and reaching for a metaclass, stop and ask whether a class decorator or __init_subclass__ solves the problem. They almost always do, and they are significantly easier to understand, test, and debug. A metaclass that the next developer has to spend an hour understanding is a liability. The best metaclass is usually the one you did not have to write.


Further Reading