一.类为什么要被阻止实例化
最常见的用途是创建只包含静态方法和类方法的工具类(注意不是说静态方法和类方法不能被实例化,不是所有工具类需要禁止实例化)
eg:
class NoInstances(type): def __call__(cls, *args, **kwargs): raise TypeError class MathUtils(metaclass=NoInstances): @staticmethod def add(a, b): return a + b @staticmethod def multiply(a, b): return a * b result = MathUtils.add(5, 3) print(result) math=MathUtils() #运行到这里会有TypeError的错误
二.具体方法
1.抽象基类
运用抽象基类,不能直接被实例化。只能在继承使用并且子类必须实现抽象基类中定义的抽象方法才可以被实例化
eg:
from abc import ABCMeta,abstractmethod class Fruit(metaclass=ABCMeta): def __init__(self,name): self.name=name @abstractmethod def health(self): pass fruit=Fruit('fruit') #TypeError (这后面是运用抽象基类可以实例化的方法) class Apple(Fruit): #1.实现继承 def health(self): #2.实现抽象基类中定义的抽象方法 print('health') apple=Apple('apple') #可以被实例化 apple.health()
扩展(对抽象基类的进一步介绍):可以起到一定的提前错误预警功能(一般用于多个类有相同的功能)
eg:
from abc import ABCMeta,abstractmethod class Fruit(metaclass=ABCMeta): def __init__(self,name): self.name=name @abstractmethod def health(self): pass class Apple(Fruit): def health(self): print('apple') class Banana(Fruit): def health(self): print('Banana') apple=Apple('apple') banana=Banana('apple')
比如说这里如果一个类中health方法命名错误,创建实例化对象时就能报错
2.元类
eg:
class NoInstances(type): def __call__(cls, *args, **kwargs): raise TypeError class C(metaclass=NoInstances): pass c=C()
实现原理:因为这里C是元类的对象,当一个对象作为函数被调用时(同时也是实例化的同时)会调用call魔法方法而就行报错,阻止类被实例化
3.继承
eg:
class NoInstances: def __init__(self): raise TypeError class C(NoInstances): pass c=C()
因为这里对象创建时会自动调用init