What are metaclasses in Python and how are they used?
In the first example, we are going to explore metaclasses in Python by creating a custom metaclass to track the number of instances created from a class.
Explanation: 1. We define a custom metaclass InstanceCounter that inherits from type . 2. In the __new__ method, we add an instance_count attribute to the class dictionary to track the number of instances created. 3. In the __call__ method, we increment the instance_count each time a new instance is created. 4. We create a class MyClass using the InstanceCounter metaclass. 5. We create two instances of MyClass and print the instance_count , which shows the number of instances created. In the second example, we are going to use a metaclass to enforce a Singleton design pattern in Python.
Explanation: 1. We define a custom metaclass Singleton that maintains a dictionary _instances to store instances of classes. 2. In the __call__ method, we check if an instance of the class already exists in _instances . If not, we create a new instance and store it. 3. We create a class SingletonClass using the Singleton metaclass, enforcing the Singleton design pattern. 4. We create two instances obj1 and obj2 of SingletonClass with different data. 5. When we print obj1.data and obj2.data , we see that both instances point to the same object, demonstrating the Singleton pattern. 6. Finally, we check if obj1 and obj2 refer to the same instance using the is keyword, which returns True as expected.
class InstanceCounter(type): def __new__(cls, name, bases, dct): dct['instance_count'] = 0 return super().__new__(cls, name, bases, dct) def __call__(self, *args, **kwargs): instance = super().__call__(*args, **kwargs) self.instance_count += 1 return instance class MyClass(metaclass=InstanceCounter): def __init__(self): pass obj1 = MyClass() obj2 = MyClass() print(MyClass.instance_count) # Output: 2
Explanation: 1. We define a custom metaclass InstanceCounter that inherits from type . 2. In the __new__ method, we add an instance_count attribute to the class dictionary to track the number of instances created. 3. In the __call__ method, we increment the instance_count each time a new instance is created. 4. We create a class MyClass using the InstanceCounter metaclass. 5. We create two instances of MyClass and print the instance_count , which shows the number of instances created. In the second example, we are going to use a metaclass to enforce a Singleton design pattern in Python.
class Singleton(type): _instances = {} def __call__(cls, *args, **kwargs): if cls not in cls._instances: cls._instances[cls] = super().__call__(*args, **kwargs) return cls._instances[cls] class SingletonClass(metaclass=Singleton): def __init__(self, data): self.data = data obj1 = SingletonClass("First Instance") obj2 = SingletonClass("Second Instance") print(obj1.data) # Output: Second Instance print(obj2.data) # Output: Second Instance print(obj1 is obj2) # Output: True
Explanation: 1. We define a custom metaclass Singleton that maintains a dictionary _instances to store instances of classes. 2. In the __call__ method, we check if an instance of the class already exists in _instances . If not, we create a new instance and store it. 3. We create a class SingletonClass using the Singleton metaclass, enforcing the Singleton design pattern. 4. We create two instances obj1 and obj2 of SingletonClass with different data. 5. When we print obj1.data and obj2.data , we see that both instances point to the same object, demonstrating the Singleton pattern. 6. Finally, we check if obj1 and obj2 refer to the same instance using the is keyword, which returns True as expected.
Comments
Post a Comment