Advanced Oops
Advanced Oops
Reading Material
Topics Covered in This Chapter:
1. Metaclasse
Understanding Metaclasse
Creating Custom Metaclasse
Use Cases for Metaclasse
The __new__ Method,__Init__Metho
Metaclass Inheritance
Font Size: 11
Code Font Style: Roboto Mono : Example —--------> git clone <repository URL>
1. Metaclasses
Understanding Metaclasses:
Imagine you're a wizard who can create magical creatures. Now, what if you could create a spell that
determines how all future magical creatures are made? That's kind of what a metaclass does in Python!
A metaclass is a class that defines how other classes are created. It's like a class factory - it makes classes!
In Python, everything is an object, even classes. And just like objects are instances of classes, classes
themselves are instances of metaclasses. The default metaclass in Python is called `type`.
PW Skills
```python
class MyMetaclass(type):
class MyClass(metaclass=MyMetaclass):
pass
obj = MyClass()
```
In this example, `MyMetaclass` adds a `greet` method to any class that uses it as a metaclass.
- `__new__` is called to create the class object. It's where you can modify the class before it's created.
- `__init__` is called to initialize the class object after it's been created.
```python
class MyMetaclass(type):
class MyClass(metaclass=MyMetaclass):
pass
# Output:
PW Skills
Metaclass Inheritance:
Metaclasses can inherit from each other, just like regular classes:
```python
class MetaA(type):
def show(cls):
class MetaB(MetaA):
def display(cls):
class MyClass(metaclass=MetaB):
pass
```
Metaclasses are a powerful feature, but they're rarely needed in everyday programming. They're mostly used in
advanced frameworks and libraries.
Multiple inheritance is when a class inherits from more than one parent class. It's like having superpowers from
both your mom and dad!
```python
class Flying:
def fly(self):
class Swimming:
def swim(self):
pass
donald = Duck()
```
PW Skills
Method Resolution Order (MRO):
When a class inherits from multiple parents, Python needs to know in which order to look for methods. This order
is called the Method Resolution Order (MRO).
```python
class A:
def show(self):
class B(A):
def show(self):
class C(A):
def show(self):
pass
d = D()
Explanation:
According to the MRO, Python first checks if Class D has a show() method. If not, it checks Class B (since B is
listed before C in the class definition of D). Python finds and executes the show() method from Class B.
PW Skills
The C3 Linearization Algorithm:
Python uses the C3 linearization algorithm to determine the MRO. It's a bit complex, but the main idea is to keep
the inheritance graph consistent and avoid conflicts.
Note:
The C3 algorithm is a deterministic MRO algorithm that ensures a single consistent order in any inheritance
hierarchy.
Children precede their parents: If class A inherits from class B, A must appear before B in the MRO.
Preserve the order of appearance in the base class list: If class C is defined as class C(B, A):, then B should
appear before A in the MRO of C.
The `super()` function is used to call methods from parent classes. In multiple inheritance, it follows the MRO.
```python
class A:
def greet(self):
class B(A):
def greet(self):
class C(A):
def greet(self):
def greet(self):
d = D()
print(d.greet())
# Output: Hello from Dada ji and Chacha and Papa and Gullak
```
The diamond problem occurs when a class inherits from two classes that have a common ancestor.
```python
class A:
def greet(self):
class B(A):
def greet(self):
PW Skills
class C(A):
def greet(self):
pass
d = D()
```
Python's MRO resolves this by following the order of inheritance and the C3 linearization algorithm.
A decorator is like a wrapper for your function. It allows you to add new functionality to an existing function
without modifying its structure.
```python
def uppercase_decorator(func):
def wrapper():
result = func()
return result.upper()
return wrapper
@uppercase_decorator
def greet():
```
Class Decorators:
Class decorators are similar to function decorators, but they work on classes instead of functions.
```python
def add_greeting(cls):
return cls
@add_greeting
class MyClass:
pass
obj = MyClass()
```
PW Skills
Decorators with Arguments:
```python
def repeat(times):
def decorator(func):
for _ in range(times):
return result
return wrapper
return decorator
@repeat(3)
def say_hello():
print("Hello!")
say_hello()
# Output:
# Hello!
# Hello!
# Hello!
```
Stacking Decorators:
You can apply multiple decorators to a single function. They are applied from bottom to top.
```python
def bold(func):
def wrapper():
return wrapper
def italic(func):
def wrapper():
return wrapper
@bold
@italic
def greet():
```
PW Skills
Wrapping Decorators:
To preserve the metadata of the original function, use the `@wraps` decorator from the `functools` module.
```python
def my_decorator(func):
@wraps(func)
return wrapper
@my_decorator
def greet(name):
```
Built-in Decorators:
```python
class Circle:
self._radius = radius
@property
def area(self):
c = Circle(5)
```
PW Skills
2. `@classmethod`: Defines a method that works with the class, rather than instances.
```python
class Person:
count = 0
self.name = name
Person.count += 1
@classmethod
def number_of_people(cls):
return cls.count
Person("Alice")
Person("Bob")
print(Person.number_of_people()) # Output: 2
```
3. `@staticmethod`: Defines a method that doesn't need access to the class or instance.
```python
class MathOperations:
@staticmethod
return x + y
```
These advanced OOP concepts provide powerful tools for creating flexible and efficient code structures. While
they may seem complex at first, with practice, they become valuable techniques in a programmer's toolkit.
PW Skills