ℹ️ Skipped - page is already crawled
| Filter | Status | Condition | Details |
|---|---|---|---|
| HTTP status | PASS | download_http_code = 200 | HTTP 200 |
| Age cutoff | PASS | download_stamp > now() - 6 MONTH | 0.1 months ago |
| History drop | PASS | isNull(history_drop_reason) | No drop reason |
| Spam/ban | PASS | fh_dont_index != 1 AND ml_spam_score = 0 | ml_spam_score=0 |
| Canonical | PASS | meta_canonical IS NULL OR = '' OR = src_unparsed | Not set |
| Property | Value |
|---|---|
| URL | https://www.geeksforgeeks.org/python/metaprogramming-metaclasses-python/ |
| Last Crawled | 2026-04-10 05:37:07 (2 days ago) |
| First Indexed | 2025-07-05 13:48:03 (9 months ago) |
| HTTP Status Code | 200 |
| Meta Title | Metaprogramming with Metaclasses in Python - GeeksforGeeks |
| Meta Description | Your All-in-One Learning Portal: GeeksforGeeks is a comprehensive educational platform that empowers learners across domains-spanning computer science and programming, school education, upskilling, commerce, software tools, competitive exams, and more., Your All-in-One Learning Portal. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions. |
| Meta Canonical | null |
| Boilerpipe Text | Metaprogramming in
Python
lets us write code that can modify or generate other code at runtime. One of the key tools for achieving this is metaclasses, which allow us to control the creation and behavior of classes.
What Are Metaclasses?
Metaclasses
are classes that define how other classes are created. While regular classes act as blueprints for creating
objects
, metaclasses serve as blueprints for creating classes themselves. When we create a class in Python, it is, in fact, an instance of a metaclass. By default, every class in Python is an instance of the built-in type metaclass.
This whole meta thing can be summarized as -
Metaclass create Classes and Classes creates objects
.
The metaclass is responsible for the generation of classes, so we can write our custom metaclasses to modify the way classes are generated by performing extra actions or injecting code. Usually, we do not need custom metaclasses but sometimes it's necessary.
Creating custom Metaclass
To create our custom metaclass, our custom metaclass has to inherit
type
metaclass and usually override -
__new__()
: It's a method which is called before __init__(). It creates the object and returns it. We can override this method to control how the objects are created.
__init__()
: This method just initialize the created object passed as a parameter
We can create classes using the
type()
function directly. It can be called in following ways -
When called with only one argument, it returns the type. We have seen it before in the above examples.
When called with three parameters, it creates a class. Following arguments are passed to it -
Class name
Tuple having base classes inherited by class
Class Dictionary:
It serves as a local namespace for the class, populated with class methods and variables
Consider this example -
Output
Type of Test class: <class 'type'>
Type of obj: <class '__main__.Test'>
This is inherited method!
This is Test class method!
ankit
Explanation:
test
Method prints "This is Test class method!".
Base
Class has myfun method that prints "This is inherited method!".
Dynamic Test Class
is created with
type()
, inherits from
Base
, adds
x="ankit"
and
my_method=test
.
Prints types of
Test
and
obj
, calls
myfun()
and
my_method()
, then prints
x
("ankit").
Now let's create a metaclass without using
type()
directly. In the following example, we will be creating a metaclass
MultiBases
which will check if the class being created has inherited from more than one base class. If so, it will raise an error.
Output:
Traceback (most recent call last):
File "main.py", line 20, in <module>
class C(A, B):
File "main.py", line 6, in __new__
raise TypeError("Inherited multiple base classes!!!")
TypeError: Inherited multiple base classes!!!
Explanation:
This code defines a custom metaclass
MultiBases
that restricts classes from inheriting from more than one base class. In the
__new__
method, it checks if the class has more than one base class and raises a
TypeError
if so. The
Base
class uses this metaclass, and while
A
and
B
(subclasses of Base) don't raise any errors,
C
(inheriting from both
A
and
B
) triggers a
TypeError
.
Solving problems with metaclass
Some problems in Python can be solved using
decorators
or
metaclasses
. While decorators provide a simple solution for many tasks, there are certain situations where only
metaclasses
can provide a more efficient or scalable solution.
Problem: Debugging Class Methods
The task is to debug class methods, meaning every time a method is executed, it should print its fully qualified name before executing its body.
Solution 1: Using Method Decorators
Here's an implementation using method decorators to debug the methods of a class:
Output
Full name of this method: Calc.add
5
Full name of this method: Calc.mul
10
Explanation:
debug Decorator:
This decorator prints the fully qualified name of the method (
func.__qualname__
) and then calls the method.
debugmethods Class Decorator:
This decorator scans the class dictionary for callable methods and applies the
debug
decorator to them.
Calc Class:
The
Calc
class uses the
@debugmethods
decorator, so its methods (
add
,
mul
, and
div
) will print their fully qualified names when called.
Solution 2: Using a Metaclass
Now, let's look at a metaclass-based solution that automatically applies the debugging functionality to all subclasses of a base class.
Output
Full name of this method: Calc_adv.mul
6
Explanation:
debug Decorator:
Same as in the first solution, it prints the fully qualified name of the method and calls it.
debugmethods Class Decorator:
This applies the
debug
decorator to all methods of a class.
debugMeta Metaclass:
The
debugMeta
metaclass overrides the
__new__
method to automatically apply the debugmethods decorator to the class when it is created. This ensures that all methods in any class using this metaclass will have debugging enabled without needing to explicitly apply the decorator.
Base Class:
The
Base
class uses the
debugMeta
metaclass, so all subclasses will automatically have debugging applied to their methods.
When to use Metaclasses
Most of the time we do not use metaclasses, it's usually used for something complicated, but a few cases where we use metaclasses are -
As we have seen in the above example, metaclasses propagate down the inheritance hierarchies. It will affect all the subclasses as well. If we have such a situation, then we should use metaclasses.
If we want to change class automatically, when it is created, we use metaclasses
For API development, we might use metaclasses
As quoted by Tim Peters
Metaclasses are deeper magic that 99% of users should never worry about. If you wonder whether you need them, you don't (the people who actually need them know with certainty that they need them, and don't need an explanation about why). |
| Markdown | [](https://www.geeksforgeeks.org/)

- Sign In
- [Courses]()
- [Tutorials]()
- [Interview Prep]()
- [Python Tutorial](https://www.geeksforgeeks.org/python/python-programming-language-tutorial/)
- [Data Types](https://www.geeksforgeeks.org/python/python-data-types/)
- [Interview Questions](https://www.geeksforgeeks.org/python/python-interview-questions/)
- [Examples](https://www.geeksforgeeks.org/python/python-programming-examples/)
- [Quizzes](https://www.geeksforgeeks.org/python/python-quizzes/)
- [DSA Python](https://www.geeksforgeeks.org/dsa/python-data-structures-and-algorithms/)
- [Data Science](https://www.geeksforgeeks.org/data-science/data-science-with-python-tutorial/)
- [NumPy](https://www.geeksforgeeks.org/python/numpy-tutorial/)
- [Pandas](https://www.geeksforgeeks.org/pandas/pandas-tutorial/)
- [Practice](https://www.geeksforgeeks.org/dsa/geeksforgeeks-practice-best-online-coding-platform/)
# Metaprogramming with Metaclasses in Python
Last Updated : 12 Apr, 2025
Metaprogramming in [Python](https://www.geeksforgeeks.org/python/python-programming-language-tutorial/) lets us write code that can modify or generate other code at runtime. One of the key tools for achieving this is metaclasses, which allow us to control the creation and behavior of classes.
## What Are Metaclasses?
[Metaclasses](https://www.geeksforgeeks.org/python/python-metaclasses/) are classes that define how other classes are created. While regular classes act as blueprints for creating [objects](https://www.geeksforgeeks.org/python/python-classes-and-objects/), metaclasses serve as blueprints for creating classes themselves. When we create a class in Python, it is, in fact, an instance of a metaclass. By default, every class in Python is an instance of the built-in type metaclass.
This whole meta thing can be summarized as - ****Metaclass create Classes and Classes creates objects****.

The metaclass is responsible for the generation of classes, so we can write our custom metaclasses to modify the way classes are generated by performing extra actions or injecting code. Usually, we do not need custom metaclasses but sometimes it's necessary.
## Creating custom Metaclass
To create our custom metaclass, our custom metaclass has to inherit ****type**** metaclass and usually override -
- [\_\_new\_\_()](https://www.geeksforgeeks.org/python/__new__-in-python/): It's a method which is called before \_\_init\_\_(). It creates the object and returns it. We can override this method to control how the objects are created.
- [\_\_init\_\_()](https://www.geeksforgeeks.org/python/__init__-in-python/): This method just initialize the created object passed as a parameter
We can create classes using the [type()](https://www.geeksforgeeks.org/python/python-type-function/) function directly. It can be called in following ways -
1. When called with only one argument, it returns the type. We have seen it before in the above examples.
2. When called with three parameters, it creates a class. Following arguments are passed to it -
1. Class name
2. Tuple having base classes inherited by class
3. ****Class Dictionary:**** It serves as a local namespace for the class, populated with class methods and variables
Consider this example -
Python
``
```
def test(self):
```
```
print("This is Test class method!")
```
```
```
```
class Base:
```
```
def myfun(self):
```
```
print("This is inherited method!")
```
```
```
```
# Creating Test class dynamically using type()
```
```
Test = type('Test', (Base, ), dict(x="ankit", my_method=test))
```
```
```
```
print("Type of Test class: ", type(Test))
```
```
```
```
obj = Test()
```
```
print("Type of obj: ", type(obj))
```
```
```
```
obj.myfun()
```
```
```
```
obj.my_method()
```
```
```
```
print(obj.x)
```
**Output**
```
Type of Test class: <class 'type'>
Type of obj: <class '__main__.Test'>
This is inherited method!
This is Test class method!
ankit
```
****Explanation:****
- ****test**** Method prints "This is Test class method!".
- ****Base**** Class has myfun method that prints "This is inherited method!".
- ****Dynamic Test Class**** is created with ****type()****, inherits from ****Base****, adds ****x="ankit"**** and ****my\_method=test****.
- Prints types of ****Test**** and ****obj****, calls ****myfun()**** and ****my\_method()****, then prints ****x**** ("ankit").
Now let's create a metaclass without using ****type()**** directly. In the following example, we will be creating a metaclass *****MultiBases***** which will check if the class being created has inherited from more than one base class. If so, it will raise an error.
Python
``
```
class MultiBases(type):
```
```
# overriding __new__ method
```
```
def __new__(cls, clsname, bases, clsdict):
```
```
# if no of base classes is greater than 1 raise error
```
```
if len(bases)>1:
```
```
raise TypeError("Inherited multiple base classes!!!")
```
```
```
```
# else execute __new__ method of super class, ie. call __init__ of type class
```
```
return super().__new__(cls, clsname, bases, clsdict)
```
```
```
```
class Base(metaclass=MultiBases):
```
```
pass
```
```
```
```
class A(Base):
```
```
pass
```
```
```
```
class B(Base):
```
```
pass
```
```
```
```
class C(A, B):
```
```
pass
```
****Output:****
```
Traceback (most recent call last):
File "main.py", line 20, in <module>
class C(A, B):
File "main.py", line 6, in __new__
raise TypeError("Inherited multiple base classes!!!")
TypeError: Inherited multiple base classes!!!
```
****Explanation:**** This code defines a custom metaclass ****MultiBases**** that restricts classes from inheriting from more than one base class. In the ****\_\_new\_\_**** method, it checks if the class has more than one base class and raises a ****TypeError**** if so. The ****Base**** class uses this metaclass, and while ****A**** and ****B**** (subclasses of Base) don't raise any errors, ****C**** (inheriting from both ****A**** and ****B****) triggers a ****TypeError****.
## Solving problems with metaclass
Some problems in Python can be solved using [decorators](https://www.geeksforgeeks.org/python/decorators-in-python/) or ****metaclasses****. While decorators provide a simple solution for many tasks, there are certain situations where only ****metaclasses**** can provide a more efficient or scalable solution.
### Problem: Debugging Class Methods
The task is to debug class methods, meaning every time a method is executed, it should print its fully qualified name before executing its body.
### Solution 1: Using Method Decorators
Here's an implementation using method decorators to debug the methods of a class:
Python
``
```
from functools import wraps
```
```
```
```
def debug(func):
```
```
'''decorator for debugging passed function'''
```
```
```
```
@wraps(func)
```
```
def wrapper(*args, **kwargs):
```
```
print("Full name of this method:", func.__qualname__)
```
```
return func(*args, **kwargs)
```
```
return wrapper
```
```
```
```
def debugmethods(cls):
```
```
'''class decorator make use of debug decorator
```
```
to debug class methods '''
```
```
```
```
# check in class dictionary for any callable(method) if exist, replace it with debugged version
```
```
for key, val in vars(cls).items():
```
```
if callable(val):
```
```
setattr(cls, key, debug(val))
```
```
return cls
```
```
```
```
# sample class
```
```
@debugmethods
```
```
class Calc:
```
```
def add(self, x, y):
```
```
return x+y
```
```
def mul(self, x, y):
```
```
return x*y
```
```
def div(self, x, y):
```
```
return x/y
```
```
```
```
mycal = Calc()
```
```
print(mycal.add(2, 3))
```
```
print(mycal.mul(5, 2))
```
**Output**
```
Full name of this method: Calc.add
5
Full name of this method: Calc.mul
10
```
****Explanation:****
- ****debug Decorator:**** This decorator prints the fully qualified name of the method (****func.\_\_qualname\_\_****) and then calls the method.
- ****debugmethods Class Decorator:**** This decorator scans the class dictionary for callable methods and applies the ****debug**** decorator to them.
- ****Calc Class:**** The ****Calc**** class uses the ****@debugmethods**** decorator, so its methods (****add****, ****mul****, and ****div****) will print their fully qualified names when called.
### Solution 2: Using a Metaclass
Now, let's look at a metaclass-based solution that automatically applies the debugging functionality to all subclasses of a base class.
Python
``
```
from functools import wraps
```
```
```
```
def debug(func):
```
```
'''decorator for debugging passed function'''
```
```
```
```
@wraps(func)
```
```
def wrapper(*args, **kwargs):
```
```
print("Full name of this method:", func.__qualname__)
```
```
return func(*args, **kwargs)
```
```
return wrapper
```
```
```
```
def debugmethods(cls):
```
```
'''class decorator make use of debug decorator to debug class methods '''
```
```
```
```
for key, val in vars(cls).items():
```
```
if callable(val):
```
```
setattr(cls, key, debug(val))
```
```
return cls
```
```
```
```
class debugMeta(type):
```
```
'''meta class which feed created class object to debugmethod to get debug functionality enabled objects'''
```
```
```
```
def __new__(cls, clsname, bases, clsdict):
```
```
obj = super().__new__(cls, clsname, bases, clsdict)
```
```
obj = debugmethods(obj)
```
```
return obj
```
```
```
```
# base class with metaclass 'debugMeta' now all the subclass of this will have debugging applied
```
```
class Base(metaclass=debugMeta):pass
```
```
```
```
# inheriting Base
```
```
class Calc(Base):
```
```
def add(self, x, y):
```
```
return x+y
```
```
```
```
# inheriting Calc
```
```
class Calc_adv(Calc):
```
```
def mul(self, x, y):
```
```
return x*y
```
```
```
```
# Now Calc_adv object showing debugging behaviour
```
```
mycal = Calc_adv()
```
```
print(mycal.mul(2, 3))
```
**Output**
```
Full name of this method: Calc_adv.mul
6
```
****Explanation:****
- ****debug Decorator:**** Same as in the first solution, it prints the fully qualified name of the method and calls it.
- ****debugmethods Class Decorator:**** This applies the ****debug**** decorator to all methods of a class.
- ****debugMeta Metaclass:**** The ****debugMeta**** metaclass overrides the ****\_\_new\_\_**** method to automatically apply the debugmethods decorator to the class when it is created. This ensures that all methods in any class using this metaclass will have debugging enabled without needing to explicitly apply the decorator.
- ****Base Class:**** The ****Base**** class uses the ****debugMeta**** metaclass, so all subclasses will automatically have debugging applied to their methods.
## When to use Metaclasses
Most of the time we do not use metaclasses, it's usually used for something complicated, but a few cases where we use metaclasses are -
- As we have seen in the above example, metaclasses propagate down the inheritance hierarchies. It will affect all the subclasses as well. If we have such a situation, then we should use metaclasses.
- If we want to change class automatically, when it is created, we use metaclasses
- For API development, we might use metaclasses
As quoted by Tim Peters
> Metaclasses are deeper magic that 99% of users should never worry about. If you wonder whether you need them, you don't (the people who actually need them know with certainty that they need them, and don't need an explanation about why).
Comment
[A](https://www.geeksforgeeks.org/user/Atul%20Kumar/)
Atul
53
Article Tags:
Article Tags:
[Python](https://www.geeksforgeeks.org/category/programming-language/python/)
### Explore
[](https://www.geeksforgeeks.org/)

Corporate & Communications Address:
A-143, 7th Floor, Sovereign Corporate Tower, Sector- 136, Noida, Uttar Pradesh (201305)

Registered Address:
K 061, Tower K, Gulshan Vivante Apartment, Sector 137, Noida, Gautam Buddh Nagar, Uttar Pradesh, 201305
[](https://geeksforgeeksapp.page.link/gfg-app)[](https://geeksforgeeksapp.page.link/gfg-app)
- Company
- [About Us](https://www.geeksforgeeks.org/about/)
- [Legal](https://www.geeksforgeeks.org/legal/)
- [Privacy Policy](https://www.geeksforgeeks.org/legal/privacy-policy/)
- [Contact Us](https://www.geeksforgeeks.org/about/contact-us/)
- [Advertise with us](https://www.geeksforgeeks.org/advertise-with-us/)
- [GFG Corporate Solution](https://www.geeksforgeeks.org/gfg-corporate-solution/)
- [Campus Training Program](https://www.geeksforgeeks.org/campus-training-program/)
- Explore
- [POTD](https://www.geeksforgeeks.org/problem-of-the-day)
- [Job-A-Thon](https://practice.geeksforgeeks.org/events/rec/job-a-thon/)
- [Blogs](https://www.geeksforgeeks.org/category/blogs/?type=recent)
- [Nation Skill Up](https://www.geeksforgeeks.org/nation-skill-up/)
- Tutorials
- [Programming Languages](https://www.geeksforgeeks.org/computer-science-fundamentals/programming-language-tutorials/)
- [DSA](https://www.geeksforgeeks.org/dsa/dsa-tutorial-learn-data-structures-and-algorithms/)
- [Web Technology](https://www.geeksforgeeks.org/web-tech/web-technology/)
- [AI, ML & Data Science](https://www.geeksforgeeks.org/machine-learning/ai-ml-and-data-science-tutorial-learn-ai-ml-and-data-science/)
- [DevOps](https://www.geeksforgeeks.org/devops/devops-tutorial/)
- [CS Core Subjects](https://www.geeksforgeeks.org/gate/gate-exam-tutorial/)
- [Interview Preparation](https://www.geeksforgeeks.org/aptitude/interview-corner/)
- [Software and Tools](https://www.geeksforgeeks.org/websites-apps/software-and-tools-a-to-z-list/)
- Courses
- [ML and Data Science](https://www.geeksforgeeks.org/courses/category/machine-learning-data-science)
- [DSA and Placements](https://www.geeksforgeeks.org/courses/category/dsa-placements)
- [Web Development](https://www.geeksforgeeks.org/courses/category/development-testing)
- [Programming Languages](https://www.geeksforgeeks.org/courses/category/programming-languages)
- [DevOps & Cloud](https://www.geeksforgeeks.org/courses/category/cloud-devops)
- [GATE](https://www.geeksforgeeks.org/courses/category/gate)
- [Trending Technologies](https://www.geeksforgeeks.org/courses/category/trending-technologies/)
- Videos
- [DSA](https://www.geeksforgeeks.org/videos/category/sde-sheet/)
- [Python](https://www.geeksforgeeks.org/videos/category/python/)
- [Java](https://www.geeksforgeeks.org/videos/category/java-w6y5f4/)
- [C++](https://www.geeksforgeeks.org/videos/category/c/)
- [Web Development](https://www.geeksforgeeks.org/videos/category/web-development/)
- [Data Science](https://www.geeksforgeeks.org/videos/category/data-science/)
- [CS Subjects](https://www.geeksforgeeks.org/videos/category/cs-subjects/)
- Preparation Corner
- [Interview Corner](https://www.geeksforgeeks.org/interview-prep/interview-corner/)
- [Aptitude](https://www.geeksforgeeks.org/aptitude/aptitude-questions-and-answers/)
- [Puzzles](https://www.geeksforgeeks.org/aptitude/puzzles/)
- [GfG 160](https://www.geeksforgeeks.org/courses/gfg-160-series)
- [System Design](https://www.geeksforgeeks.org/system-design/system-design-tutorial/)
[@GeeksforGeeks, Sanchhaya Education Private Limited](https://www.geeksforgeeks.org/), [All rights reserved](https://www.geeksforgeeks.org/copyright-information/)
![]() |
| Readable Markdown | Metaprogramming in [Python](https://www.geeksforgeeks.org/python/python-programming-language-tutorial/) lets us write code that can modify or generate other code at runtime. One of the key tools for achieving this is metaclasses, which allow us to control the creation and behavior of classes.
## What Are Metaclasses?
[Metaclasses](https://www.geeksforgeeks.org/python/python-metaclasses/) are classes that define how other classes are created. While regular classes act as blueprints for creating [objects](https://www.geeksforgeeks.org/python/python-classes-and-objects/), metaclasses serve as blueprints for creating classes themselves. When we create a class in Python, it is, in fact, an instance of a metaclass. By default, every class in Python is an instance of the built-in type metaclass.
This whole meta thing can be summarized as - ****Metaclass create Classes and Classes creates objects****.

The metaclass is responsible for the generation of classes, so we can write our custom metaclasses to modify the way classes are generated by performing extra actions or injecting code. Usually, we do not need custom metaclasses but sometimes it's necessary.
## Creating custom Metaclass
To create our custom metaclass, our custom metaclass has to inherit ****type**** metaclass and usually override -
- [\_\_new\_\_()](https://www.geeksforgeeks.org/python/__new__-in-python/): It's a method which is called before \_\_init\_\_(). It creates the object and returns it. We can override this method to control how the objects are created.
- [\_\_init\_\_()](https://www.geeksforgeeks.org/python/__init__-in-python/): This method just initialize the created object passed as a parameter
We can create classes using the [type()](https://www.geeksforgeeks.org/python/python-type-function/) function directly. It can be called in following ways -
1. When called with only one argument, it returns the type. We have seen it before in the above examples.
2. When called with three parameters, it creates a class. Following arguments are passed to it -
1. Class name
2. Tuple having base classes inherited by class
3. ****Class Dictionary:**** It serves as a local namespace for the class, populated with class methods and variables
Consider this example -
**Output**
```
Type of Test class: <class 'type'>
Type of obj: <class '__main__.Test'>
This is inherited method!
This is Test class method!
ankit
```
****Explanation:****
- ****test**** Method prints "This is Test class method!".
- ****Base**** Class has myfun method that prints "This is inherited method!".
- ****Dynamic Test Class**** is created with ****type()****, inherits from ****Base****, adds ****x="ankit"**** and ****my\_method=test****.
- Prints types of ****Test**** and ****obj****, calls ****myfun()**** and ****my\_method()****, then prints ****x**** ("ankit").
Now let's create a metaclass without using ****type()**** directly. In the following example, we will be creating a metaclass *****MultiBases***** which will check if the class being created has inherited from more than one base class. If so, it will raise an error.
****Output:****
```
Traceback (most recent call last):
File "main.py", line 20, in <module>
class C(A, B):
File "main.py", line 6, in __new__
raise TypeError("Inherited multiple base classes!!!")
TypeError: Inherited multiple base classes!!!
```
****Explanation:**** This code defines a custom metaclass ****MultiBases**** that restricts classes from inheriting from more than one base class. In the ****\_\_new\_\_**** method, it checks if the class has more than one base class and raises a ****TypeError**** if so. The ****Base**** class uses this metaclass, and while ****A**** and ****B**** (subclasses of Base) don't raise any errors, ****C**** (inheriting from both ****A**** and ****B****) triggers a ****TypeError****.
## Solving problems with metaclass
Some problems in Python can be solved using [decorators](https://www.geeksforgeeks.org/python/decorators-in-python/) or ****metaclasses****. While decorators provide a simple solution for many tasks, there are certain situations where only ****metaclasses**** can provide a more efficient or scalable solution.
### Problem: Debugging Class Methods
The task is to debug class methods, meaning every time a method is executed, it should print its fully qualified name before executing its body.
### Solution 1: Using Method Decorators
Here's an implementation using method decorators to debug the methods of a class:
**Output**
```
Full name of this method: Calc.add
5
Full name of this method: Calc.mul
10
```
****Explanation:****
- ****debug Decorator:**** This decorator prints the fully qualified name of the method (****func.\_\_qualname\_\_****) and then calls the method.
- ****debugmethods Class Decorator:**** This decorator scans the class dictionary for callable methods and applies the ****debug**** decorator to them.
- ****Calc Class:**** The ****Calc**** class uses the ****@debugmethods**** decorator, so its methods (****add****, ****mul****, and ****div****) will print their fully qualified names when called.
### Solution 2: Using a Metaclass
Now, let's look at a metaclass-based solution that automatically applies the debugging functionality to all subclasses of a base class.
**Output**
```
Full name of this method: Calc_adv.mul
6
```
****Explanation:****
- ****debug Decorator:**** Same as in the first solution, it prints the fully qualified name of the method and calls it.
- ****debugmethods Class Decorator:**** This applies the ****debug**** decorator to all methods of a class.
- ****debugMeta Metaclass:**** The ****debugMeta**** metaclass overrides the ****\_\_new\_\_**** method to automatically apply the debugmethods decorator to the class when it is created. This ensures that all methods in any class using this metaclass will have debugging enabled without needing to explicitly apply the decorator.
- ****Base Class:**** The ****Base**** class uses the ****debugMeta**** metaclass, so all subclasses will automatically have debugging applied to their methods.
## When to use Metaclasses
Most of the time we do not use metaclasses, it's usually used for something complicated, but a few cases where we use metaclasses are -
- As we have seen in the above example, metaclasses propagate down the inheritance hierarchies. It will affect all the subclasses as well. If we have such a situation, then we should use metaclasses.
- If we want to change class automatically, when it is created, we use metaclasses
- For API development, we might use metaclasses
As quoted by Tim Peters
> Metaclasses are deeper magic that 99% of users should never worry about. If you wonder whether you need them, you don't (the people who actually need them know with certainty that they need them, and don't need an explanation about why). |
| Shard | 103 (laksa) |
| Root Hash | 12046344915360636903 |
| Unparsed URL | org,geeksforgeeks!www,/python/metaprogramming-metaclasses-python/ s443 |