zoukankan      html  css  js  c++  java
  • 面向对象-元类

     http://www.cnblogs.com/linhaifeng/articles/8029564.html

    类的类就为元类

    元类所需知识

    #exec()
    #参数1:字符串形式的命令
    #参数2:全局作用域(字典形式),不指定默认使用全局globals()
    #参数3:局部作用域(字典形式),不指定默认使用局部locals()
    g={'x':1,
       'y':2}
    l={}
    #把exec中代码当一个函数来看待
    exec("""
    global x,m
    x=10
    m=100
    z=3""",g,l)
    print(g)
    print(l)

    一切皆对象,对象可以怎么来用,共性?

    1. 都可以被应用,x=obj
    2. 都可以当函数的参数传入
    3. 都可以当函数的返回值
    4. 都可以当作容器类型的元素,如都可当列表的元素
    #类也是一个对象
    class Foo:
        pass
    obj=Foo()
    print(type(obj))
    print(type(Foo))

    • 产生类的类称之为元类,默认所有用class定义的类,他们的元类是type

    定义类的方式

    #方式一定义类:
    class Chinese:
        country='China'
        def __init__(self,name,age):
            self.name=name
            self.age=age
        def talks(self):
            print("%s is talking" % self.name)
    
    #方式二定义类:
    #定义类的三要素
    # 类名,类的基类,类的命名空间
    class_name='Chinese'
    class_base=(object,)
    class_body="""
    country='China'
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def talks(self):
        print("%s is talking" % self.name)
    """
    class_dic={}
    exec(class_body,globals(),class_dic)
    Chinese1=type(class_name,class_base,class_dic)
    print(Chinese)
    print(Chinese1)

    自定义元类来控制类的创建

     自己写一个元类

    #自定义一个元类,因需要使用类中的其他方法,所以自定义元类继承于type
    class Mymeta(type):
        def __init__(self,class_name,class_bases,class_dic):
            print(class_name)#打印类名字
            print(class_bases)#打印类的基类
            print(class_dic)#打印类的名称空间
            super(Mymeta,self).__init__(class_name,class_bases,class_dic)#引用父类方法
    #定义一个类,继承于自己定义的元类
    class Chinese(object,metaclass=Mymeta):
        country='China'
        def __init__(self,name,age):
            self.name=name
            self.age=age
        def talks(self):
            print("%s is talking" % self.name)

    对元类进行控制,以达到自定义

    #自定义元类,控制类的行为
    class Mymeta(type):
        def __init__(self,class_name,class_bases,class_dic):
            #强制首字母大写
            if not class_name.istitle():
                raise TypeError("类名首字母必须大写")
            #强制写注释
            if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
                raise TypeError("类必须有注释,且不为空")
            print(class_dic)
            super(Mymeta,self).__init__(class_name,class_bases,class_dic)#引用父类方法
    #定义一个类,继承于自己定义的元类
    class chinese(object,metaclass=Mymeta):
        country='China'
        def __init__(self,name,age):
            self.name=name
            self.age=age
        def talks(self):
            print("%s is talking" % self.name)

    #自定义元类,控制类的行为
    class Mymeta(type):
        def __init__(self,class_name,class_bases,class_dic):
            #强制首字母大写
            if not class_name.istitle():
                raise TypeError("类名首字母必须大写")
            #强制写注释
            if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
                raise TypeError("类必须有注释,且不为空")
            print(class_dic)
            super(Mymeta,self).__init__(class_name,class_bases,class_dic)#引用父类方法
    #定义一个类,继承于自己定义的元类
    class Chinese(object,metaclass=Mymeta):
        country='China'
        def __init__(self,name,age):
            self.name=name
            self.age=age
        def talks(self):
            print("%s is talking" % self.name)

    自定义元类控制类实例化行为

    知识储备__call__()

    #知识储备__call__方法
    class Foo:
        def __call__(self, *args, **kwargs):
            print(self)
            print(args)
            print(kwargs)
    obj=Foo()
    obj(1,2,3,a=4,b=5)
    View Code

    Foo默认继承元类,那么元类中则有一个__call__方法,会在调用Foo时会触发

    Foo(1,2,3)等同于Foo.__call__(Foo,1,2,3)

     自定义一个元类来控制类的实例化

    #自定义元类,控制类的行为
    class Mymeta(type):
        def __init__(self,class_name,class_bases,class_dic):
            #强制首字母大写
            if not class_name.istitle():
                raise TypeError("类名首字母必须大写")
            #强制写注释
            if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
                raise TypeError("类必须有注释,且不为空")
            super(Mymeta,self).__init__(class_name,class_bases,class_dic)#引用父类方法
        def __call__(self, *args, **kwargs):
            #1、制造一个空对象obj
            obj=object.__new__(self)
            #2、初始化obj
            self.__init__(obj,*args,**kwargs)
            #3、返回obj
            return obj
    #定义一个类,继承于自己定义的元类
    class Chinese(object,metaclass=Mymeta):
        """中文人的类"""
        country='China'
        def __init__(self,name,age):
            self.name=name
            self.age=age
        def talks(self):
            print("%s is talking" % self.name)
    obj=Chinese('ya',18)#Chinese.__call__(Chinese,'ya,18)
    print(obj.__dict__)
    View Code

    验证创建是否成功

    自定义元类控制类的实例化应用

     单例模式

    #单例模式,参数一样的对象就不要多次创建多次占用内存
    class MySQL:
        def __init__(self):
            self.host='127.0.0.1'
            self.port=3306
    
    obj1=MySQL()
    obj2=MySQL()
    obj3=MySQL()
    print(obj1)
    print(obj2)
    print(obj3)
    View Code

    单例模式的实现

    class MySQL:
        __instance=None
        def __init__(self):
            self.host='127.0.0.1'
            self.port=3306
        @classmethod
        def singleton(cls):
            if not cls.__instance:
                obj=cls()
                cls.__instance=obj
            return cls.__instance
        def conn(self):
            pass
        def execute(self):
            pass
    obj1=MySQL.singleton()
    obj2=MySQL.singleton()
    obj3=MySQL.singleton()
    print(obj1)
    print(obj2)
    print(obj3)
    View Code

    通过元类来实现单例模式

    #元类实现单例模式
    class Mymeta(type):
        def __init__(self,class_name,class_bases,class_dic):
            #强制首字母大写
            if not class_name.istitle():
                raise TypeError("类名首字母必须大写")
            #强制写注释
            if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
                raise TypeError("类必须有注释,且不为空")
            super(Mymeta,self).__init__(class_name,class_bases,class_dic)#继承父类方法
            self.__instance=None
        def __call__(self, *args, **kwargs):
            if not self.__instance:
                obj=object.__new__(self)
                self.__init__(obj)
                self.__instance=obj
            return self.__instance
    class Mysql(object,metaclass=Mymeta):
        """
        Mysql
        """
        def __init__(self):
            self.host='127.0.0.1'
            self.port=3306
        def conn(self):
            pass
        def execute(self):
            pass
    
    obj1=Mysql()
    obj2=Mysql()
    obj3=Mysql()
    print(obj1)
    print(obj2)
    print(obj3)
    View Code

  • 相关阅读:
    Linux 文件系统满,查找大文件的方法
    STM32 HAL库重新设置中断向量表后,无法进入中断的解决方法
    C指针
    vs code 代码片段设置时遇到的几个小问题
    堆排序详解
    Java final和c++ const区别
    白话经典之String字符串详解
    java之SSH框架面试
    JSTL入门指南
    LeetCode(9):Palindrome Number
  • 原文地址:https://www.cnblogs.com/yaya625202/p/8890507.html
Copyright © 2011-2022 走看看