Summary - Metaprogramming
- Python course
- Expert
- Lesson 6/47
- 5 min
Combine type, metaclass and __init_subclass__ to write a DSL.
Recap: metaprogramming tools
In this group you learned four tools. type() for dynamic classes, metaclass to intercept class creation, __init_subclass__ as a lightweight hook, __class_getitem__ for subscripting, @decorator to wrap a class.
Now you will combine them into a mini DSL: a Field descriptor and a ModelMeta metaclass. Field learns its name via __set_name__; the metaclass collects fields into a fields list. This is the core idea behind Django and SQLAlchemy.
Practice Mini DSL: Field + metaclass
Write a Field class with a __set_name__(self, owner, name) method; it sets self.name = name, creates owner.fields = [] if missing and appends name. Write a ModelMeta(type) metaclass whose __new__ returns super().__new__. In User(metaclass=ModelMeta) define name = Field(). Print User.fields.
Starter code
# Write Field descriptor and ModelMeta
# use Field in the User class
# print the field namesSample solution
# Write Field descriptor and ModelMeta
class Field:
def __set_name__(self, owner, name):
self.name = name
if not hasattr(owner, "fields"):
owner.fields = []
owner.fields.append(name)
class ModelMeta(type):
def __new__(mcs, name, bases, ns):
return super().__new__(mcs, name, bases, ns)
class User(metaclass=ModelMeta):
name = Field()
print(User.fields)Expected output
['name']
What you learned
In this group you went deep into Python's class creation mechanism. You learned to build a class by hand with type(), intercept the process with a metaclass, and write lightweight hooks with __init_subclass__.
You also saw __class_getitem__ for generic-looking APIs and @decorator to add behavior after the fact. In the summary you combined these into a mini DSL: a Field descriptor + metaclass. This pattern is the backbone of major Python frameworks.
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 Which tool for which job?
- type() for dynamic classes
- __init_subclass__ for subclass hooks
- metaclass to create instances
- @decorator to wrap a class Correct answer
Explanation: @decorator wraps a class; creating instances is __init__'s job.
2 Match all metaprogramming concepts
| Term | Meaning |
|---|---|
type() |
Dynamic class |
metaclass |
Class production |
__init_subclass__ |
Subclass hook |
@decorator |
Class wrapping |
3 Final blank
class ModelMeta(type):
def __new__(mcs, name, bases, ns):
return super().____(mcs, name, bases, ns)
class ModelMeta(type):
def __new__(mcs, name, bases, ns):
return super().__new__(mcs, name, bases, ns)
Explanation: super().__new__ produces the actual class object.