Python中如何控制类的实例化过程
python中控制类的实例化过程有两种方式: 1.通过类中__new__方法, 2.通过元类编程
下面以设计单例模式为示例,来呈现控制类实例化的两种方式
首先, 单例模式需要确保一个类只有一个实例对象, 那么就需要在类的实例化过程中控制实例对象的生成逻辑
一. 基于__new__方法实现单例模式
1.1 预备知识: 理解类中new方法,init方法,call方法
1) __new__方法负责创建实例对象(创建对象时调用)
2) __init__方法负责对实例对象进行初始化
3) 如果__new__方法没有返回实例对象, 那么__init__方法是不会被调用的
4) 定义__call__方法后,实例对象可以像函数那个被调用
1.2 代码实现
# -*- coding: utf-8 -*- class Singleton(object): # 在__new__方法中控制类的实例化过程 def __new__(cls, *args, **kwargs): if not hasattr(cls, "_instance"): cls._instance = super().__new__(cls) return cls._instance # 创建两个实例对象, 对比其对象id是否相同 s1 = Singleton() s2 = Singleton() print(id(s1) == id(s2)) # True
二. 基于元类编程实现单例模式
2.1 预备知识: 如何理解元类
1) python中一切皆对象, 类也是对象, 元类就是类的类
2) 通过type可以动态的创建类, 例如 MyClass = type("MyClass ", (object, ), {})
3) type是python的内建元类, 开发者也可以自定义元类
4) 自定义元类后, 在创建类时开发者可以改变类的生成过程
2.2 代码实现
# -*- coding: utf-8 -*- # 自定义元类 class MyMetaClass(type): instance = {} def __init__(cls, *args, **kwargs): super().__init__(*args, **kwargs) # cls被调用时会调用__call__方法, 而cls被调用时正是cls类的实例化过程 def __call__(cls, *args, **kwargs): if cls not in cls.instance: cls.instance[cls] = super().__call__(*args, **kwargs) return cls.instance class Demo(metaclass=MyMetaClass): pass # 创建两个实例对象, 对比其对象id是否相同 a = Demo() b = Demo() print(id(a) == id(b)) # True
最后小结:
类的实例化过程, 可以通过__new__方法来实现, 也可以将类的实例化过程剥离出来,委托给元类来做