元类的剖析和单例

1.eval内置函数

#    eval的使用场景:
#                1.执行字符串会的到相应的结果
#                2.一般用于类型转换,得到list, dict,tuple等


dic_str = "{'a':1,'b':2,'c':3}"
print(eval(dic_str))


list_str = "[1,2,3,4,5]"
print(eval(list_str))


tu_str = "(1,2,3,4,5)"
print(eval(tu_str))
eval使用案例

2.exec内置函数

# exec应用场景
# 1.执行字符串没有执行结果(没有返回值)
# 2.将执行的字符串中产生的名字形成对应的局部名称空间

source = '''
name = 'Bob'
age = 20
'''
class A:
    pass
a = A()

dic = {}
exec(source, {}, dic)
a.__dict__ = dic
print(a.__dict__)
print(a.name)
print(a.age)
exec使用案例

3.type产生类

# 类是type的对象,可以通过type(参数)来创建类

# type(name, bases, namespace)

s = '''
my_a = 10
my_b = 20
def __init__(self):
    pass
@classmethod
def print_msg(cls, msg):
    print(msg)
'''
namespace = {}
exec(s, {}, namespace)

Student = type('Student', (object, ), namespace)

stu = Student()

4.自定义元类

# 元类:所有自定义的类本身也是对象,是元类的对象,所有自定义的类本质上是由元类实例化出来了
Student = type('Student', (object, ), namespace)

class MyMeta(type):
    # 在class Student时调用:Student类的创建 => 来控制类的创建
    
    # 自定义元类,重写init方法的目的:
    # 1.该方法是从type中继承来的,所以参数同type的init
    # 2.最终的工作(如果开辟空间,如果操作内存)还是要借助type
    # 3.在交给type最终完成工作之前,可以对类的创建加以限制 *****
    def __init__(cls, class_name, bases, namespace):
        # 目的:对class_name | bases | namespace加以限制 **********************
        super().__init__(class_name, bases, namespace)
    
    # 在Student()时调用:Student类的对象的创建 => 来控制对象的创建
    
    # 自定义元类,重写call方法的目的:
    # 1.被该元类控制的类生成对象,会调用元类的call方法
    # 2.在call中的返回值就是创建的对象
    # 3.在call中
    #       -- 通过object开辟空间产生对象
    #       -- 用被控制的类回调到自己的init方法完成名称空间的赋值
    #       -- 将修饰好的对象反馈给外界
    def __call__(cls, *args, **kwargs):
        # 目的:创建对象,就可以对对象加以限制 **********************
        obj = object.__new__(cls)  # 通过object为哪个类开辟空间
        cls.__init__(obj, *args, **kwargs)  # 调回当前被控制的类自身的init方法,完成名称空间的赋值
        return obj

# 问题:
# 1.继承是想获得父级的属性和方法,元类是要将类的创建于对象的创建加以控制
# 2.类的创建由元类的__init__方法控制
#        -- 元类(class_name, bases, namespase) => 元类.__init__来完成实例化
# 3.类的对象的创建由元类的__call__方法控制
#         -- 对象产生是需要开辟空间,在__call__中用object.__new__()来完成的
class Student(object, metaclass=MyMeta):
    pass

# class Student:  <=>  type(class_name, bases, namespace)
# 控制类的产生过程,以及该类对象的产生过程
class MyMeta(type):
    # 控制类的创建过程
    def __init__(cls, class_name, bases, namespace):
        print(cls, class_name, bases, namespace)
        super().__init__(class_name, bases, namespace)

    def __call__(cls, *args, **kwargs):
        obj = object.__new__(cls)
        cls.__init__(obj, *args, **kwargs)
        return obj

# Student类与Student类的对象产生都可以备元类MyMeta控制
class Student(metaclass=MyMeta):
    def __init__(self, name, age):
        self.name = name
        self.age = age
stu = Student('owen', 18)
print(stu.name)

5.元类的应用

class MyMeta(type):
        
        def __call__(cls, *args, **kwargs):
            if not hasattr(cls, "instance"):
                cls.instance == cls.__new__(cls)
                cls.instance.__init__(*args, **kwargs)
                return cls.instance

class A(metaclass = MyMeta):
        
        def __init(self):
            self.ip = '1.1.1.0'

6.单例

# single_module.py
class Single:
    pass
singleton = Single()

# 测试文件
from single_module import singleton
print(singleton)
print(singleton)
简单实现(模块)
class Song:

    __instance = None
    def __init__(self):
        pass
    
    @classmethod
    def getInstance(cls):
        if cls.__instance == None:
            cls.__instance = cls()
        retuen cls.__instance


s1 = Song.getInstacne()
s2 = Song.getInstacne()

print(s1, s2)
实现方式一
def sinle(cls):

    __instance = None
    def getInstacne(*args, **kwargs):
        nolocal = __instance
        if __instance == None:
            __instance = cls(*args, **kwargs)
        return __instance
    return grtInstance


@single
class  A:
    def__init(self,name):
        self.name = name

print(A(1), A(2),A(3))
实现方式二
class A:
    __instacne = None
    def __new__(cls,*args,**kwargs):
        if __instacne == None:
            cls.__instacne = super().__new__(cls)
        return cls.__inistacne

print(A(),A())
实现方式三
原文地址:https://www.cnblogs.com/wanglei957/p/10784448.html