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__方法来实现, 也可以将类的实例化过程剥离出来,委托给元类来做

 

posted @ 2021-08-23 19:53  后来者2012  阅读(360)  评论(0编辑  收藏  举报