Profile picture
, 15 tweets, 4 min read Read on Twitter
Let's talk about Python metaclasses. 🎩✨ Many think they are magical things that mere mortals should never use. That's not quite true, although in many cases metaclasses can needlessly complicate things. Beware.

Read the thread! 👇👇👇
Note: the purpose of this thread is to show how to use metaclasses via a few examples. There are a few simplifications here and there for the sake of brevity. If you want to understand how things work I suggest to start with the official documentation: docs.python.org/3/reference/da…
1. We first need to talk about regular classes, and specifically about __new__() and __init__() methods. The former is actually a static method—it's called when an instance of the class is constructed. The __init__() method then initializes that instance.
2. If we go low-level we will realize that the "class" statement is a syntax sugar. For example, the previous example is (pretty much) equivalent to this:
3. The "class" statement does a few more things than simply calling "type(...)", but that's not important here. What matters is that we have just created a class via a function call! So there's nothing super special about the "class" syntax!
4. Everything is an object in Python. Objects are instances of classes.

Classes are objects. Which means... that classes are instances of some classes... 🤯

We call classes that create classes "metaclasses".
5. A class is a metaclass when it's derived from the "type" class. To later use a metaclass, we use a slightly unintuitive (at first) syntax:
6. If you are really interested in how things work, now would be a good time to open a REPL and play with the snippet in (5). Specifically google about the "__mro__" attribute and try inspecting "FooMeta.__mro__" and "Foo.__mro__". It's not that important right now, though.
7. You only need to use "metaclass=FooMeta" syntax for the topmost class of the hierarchy. E.g. if you derive class "Bar" from "Foo" with the "class Bar(Foo)" syntax, the metaclass of Bar will be "FooMeta". That's convenient!
8. Now let's get back to __new__ and __init__ methods we talked about in (1). What if we specify them for a metaclass? We certainly can. In that case they will allow us to fully control how classes are constructed:
9. It's possible to change class bodies, class attributes and methods, names, list of base classes, and many other things via a metaclass with a "__new__()" method. People use metaclasses to automatically register classes, implement ORMs, enforce behaviours.
10. Try writing some diabolical code by overloading operators, __getitem__, or __prepare__ on metaclasses!
11. There's a complication though. When metaclasses are used with multiple inheritance, it's easy to arrive to a situation when there's more than one custom metaclass to chose from:
12. To solve (11), we added a new magic method to Python 3.6: "__init_subclass__". It allows to implement many of the things people typically use metaclasses for with a simpler pattern. E.g. here's a primitive class registry:
There are multiple legitimate use cases for metaclasses. The only way to discover those use cases is by studying how frameworks use metaclasses and by experimenting on your own. I hope that I was able to demystify metaclasses somewhat in this thread. Go discover! 🙏
Missing some Tweet in this thread?
You can try to force a refresh.

Like this thread? Get email updates or save it to PDF!

Subscribe to Yury Selivanov
Profile picture

Get real-time email alerts when new unrolls are available from this author!

This content may be removed anytime!

Twitter may remove this content at anytime, convert it as a PDF, save and print for later use!

Try unrolling a thread yourself!

how to unroll video

1) Follow Thread Reader App on Twitter so you can easily mention us!

2) Go to a Twitter thread (series of Tweets by the same owner) and mention us with a keyword "unroll" @threadreaderapp unroll

You can practice here first or read more on our help page!

Follow Us on Twitter!

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just three indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3.00/month or $30.00/year) and get exclusive features!

Become Premium

Too expensive? Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal Become our Patreon

Thank you for your support!