• 元类


    元类

    一切源自于一句话:python中一切皆为对象
    一:元类介绍
     

    """

    元类=》OldboyTeacher类=》obj

    代码

    class OldboyTeacher(object):
      school = 'oldboy'

      def __init__(self, name, age):
          self.name = name
          self.age = age
       
      def say(self):
          print('%s says welcome to the oldboy to learn Python' % self.name)


    obj = OldboyTeacher('egon', 18) # 调用OldboyTeacher类=》对象obj

     

    调用元类=》OldboyTeacher类
    print(type(obj))

    print(type(OldboyTeacher))

    结论:默认的元类是type,默认情况下我们用class关键字定义的类都是由type产生的

    """

    二:class关键字底层的做了哪些事

    '''

    1、先拿到一个类名

    class_name = "OldboyTeacher"

    2、然后拿到类的父类

    class_bases = (object,)

    3、再运行类体代码,将产生的名字放到名称空间中
    class_dic = {}
    class_body = """
    school = 'oldboy'

    def __init__(self, name, age):
      self.name = name
      self.age = age

    def say(self):
      print('%s says welcome to the oldboy to learn Python' % self.name)
    """
    exec(class_body,{},class_dic)

     

    print(class_dic)

    4、调用元类(传入类的三大要素:类名、基类、类的名称空间)得到一个元类的对象,然后将元类的对象赋值给变量名OldboyTeacher,oldboyTeacher就是我们用class自定义的那个类

    OldboyTeacher = type(class_name,class_bases,class_dic)
    '''

    三:自定义元类

    '''
    class Mymeta(type):  # 只有继承了type类的类才是自定义的元类
        pass

    class OldboyTeacher(object, metaclass=Mymeta):
        school = 'oldboy'

    def __init__(self, name, age):
      self.name = name
      self.age = age

    def say(self):
      print('%s says welcome to the oldboy to learn Python' % self.name)

    1、先拿到一个类名:"OldboyTeacher"

    2、然后拿到类的父类:(object,)
    3、再运行类体代码,将产生的名字放到名称空间中{...}
    4、调用元类(传入类的三大要素:类名、基类、类的名称空间)得到一个元类的对象,然后将元类的对象赋值给变量名OldboyTeacher,oldboyTeacher就是我们用class自定义的那个类

    OldboyTeacher = Mymeta("OldboyTeacher",(object,),{...})
    '''

    四:自定义元类来控制OldboyTeacher类的产生

    '''
    import re

    class Mymeta(type):  # 只有继承了type类的类才是自定义的元类
        def init(self, class_name, class_bases, class_dic):
            # print(self)  # 类<class 'main.OldboyTeacher'>
            # print(class_name)
            # print(class_bases)
            # print(class_dic)

        if not re.match("[A-Z]", class_name):
          raise BaseException("类名必须用驼峰体")

      if len(class_bases) == 0:
          raise BaseException("至少继承一个父类")

      # print("文档注释:",class_dic.get('__doc__'))
      doc=class_dic.get('__doc__')

      if not (doc and len(doc.strip()) > 0):
          raise BaseException("必须要有文件注释,并且注释内容不为空")

    OldboyTeacher = Mymeta("OldboyTeacher",(object,),{...})

    class OldboyTeacher(object,metaclass=Mymeta):
        """
        adsaf
        """

    school = 'oldboy'

    def __init__(self, name, age):
      self.name = name
      self.age = age

    def say(self):
      print('%s says welcome to the oldboy to learn Python' % self.name)

    '''

    五:自定义元类来控制OldboyTeacher类的调用

    '''
    import re

    class Mymeta(type):  # 只有继承了type类的类才是自定义的元类
        def init(self, class_name, class_bases, class_dic):
            # print(self)  # 类<class 'main.OldboyTeacher'>
            # print(class_name)
            # print(class_bases)
            # print(class_dic)

        if not re.match("[A-Z]", class_name):
          raise BaseException("类名必须用驼峰体")

      if len(class_bases) == 0:
          raise BaseException("至少继承一个父类")

      # print("文档注释:",class_dic.get('__doc__'))
      doc = class_dic.get('__doc__')

      if not (doc and len(doc.strip()) > 0):
          raise BaseException("必须要有文件注释,并且注释内容不为空")

    # res = OldboyTeacher('egon',18)
    def __call__(self, *args, **kwargs):
      # 1、先创建一个老师的空对象
      tea_obj = object.__new__(self)
      # 2、调用老师类内的__init__函数,然后将老师的空对象连同括号内的参数的参数一同传给__init__
      self.__init__(tea_obj, *args, **kwargs)
      tea_obj.__dict__ = {"_%s__%s" %(self.__name__,k): v for k, v in tea_obj.__dict__.items()}

      # 3、将初始化好的老师对象赋值给变量名res
      return tea_obj
    OldboyTeacher = Mymeta("OldboyTeacher",(object,),{...})

    class OldboyTeacher(object, metaclass=Mymeta):
        """
        adsaf
        """

    school = 'oldboy'

    #           tea_obj,'egon',18
    def __init__(self, name, age):
      self.name = name # tea_obj.name='egon'
      self.age = age # tea_obj.age=18

    def say(self):
      print('%s says welcome to the oldboy to learn Python' % self.name)

    res = OldboyTeacher('egon', 18)
    print(res.dict)

    print(res.name)
    print(res.age)
    print(res.say)
    调用OldboyTeacher类做的事情:
    1、先创建一个老师的空对象
    2、调用老师类内的init方法,然后将老师的空对象连同括号内的参数的参数一同传给init
    3、将初始化好的老师对象赋值给变量名res

    '''

    六:单例模式

     

    单例模式就是确保一个类只有一个实例.当你希望整个系统中,某个类只有一个实例时,单例模式就派上了用场.
    比如,某个服务器的配置信息存在在一个文件中,客户端通过AppConfig类来读取配置文件的信息.如果程序的运行的过程中,很多地方都会用到配置文件信息,则就需要创建很多的AppConfig实例,这样就导致内存中有很多AppConfig对象的实例,造成资源的浪费.其实这个时候AppConfig我们希望它只有一份,就可以使用单例模式.




    实现方式1:classmethod

    """
    import settings

    class MySQL:
        __instance = None

    def __init__(self, ip, port):
      self.ip = ip
      self.port = port

    @classmethod
    def singleton(cls):
      if cls.__instance:
          return cls.__instance
      cls.__instance = cls(settings.IP, settings.PORT)
      return cls.__instance
    obj1=MySQL("1.1.1.1",3306)
    obj2=MySQL("1.1.1.2",3306)
    print(obj1)
    print(obj2)

    obj3 = MySQL.singleton()
    print(obj3)

    obj4 = MySQL.singleton()
    print(obj4)
    """

    方式2:元类

    """
    import settings

    class Mymeta(type):
        instance = None
        def
    init(self,class_name,class_bases,class_dic):
            self.
    instance=object.new(self)  # Mysql类的对象
            self.init(self.__instance,settings.IP,settings.PORT)

    def __call__(self, *args, **kwargs):
      if args or kwargs:
          obj = object.__new__(self)
          self.__init__(obj, *args, **kwargs)
          return obj
      else:
          return self.__instance
    MySQL=Mymeta(...)

    class MySQL(metaclass=Mymeta):
        def init(self, ip, port):
            self.ip = ip
            self.port = port

    obj1 = MySQL("1.1.1.1", 3306)
    obj2 = MySQL("1.1.1.2", 3306)
    print(obj1)
    print(obj2)

    obj3 = MySQL()
    obj4 = MySQL()

    print(obj3 is obj4)
    """

    方式3:装饰器

    """
    import settings

    def outter(func):  # func = MySQl类的内存地址
        _instance = func(settings.IP,settings.PORT)
        def wrapper(args,**kwargs):
            if args or kwargs:
                res=func(
    args,**kwargs)
                return res
            else:
                return _instance
        return wrapper

    @outter  # MySQL=outter(MySQl类的内存地址)  # MySQL=》wrapper
    class MySQL:
        def init(self, ip, port):
            self.ip = ip
            self.port = port

    obj1 = MySQL("1.1.1.1", 3306)
    obj2 = MySQL("1.1.1.2", 3306)
    print(obj1)
    print(obj2)

    obj3 = MySQL()
    obj4 = MySQL()
    print(obj3 is obj4)
    """

    了解:属性查找

    class Mymeta(type):
        n=444

    # def __call__(self, *args, **kwargs): #self=<class '__main__.OldboyTeacher'>
    #     obj=self.__new__(self)
    #     print(self.__new__ is object.__new__) #True

    class Bar(object):
        # n=333

    # def __new__(cls, *args, **kwargs):
    #     print('Bar.__new__')
    pass

    class Foo(Bar):
        # n=222

    # def __new__(cls, *args, **kwargs):
    #     print('Foo.__new__')
    pass

    class OldboyTeacher(Foo,metaclass=Mymeta):
        # n=111

    school='oldboy'

    def __init__(self,name,age):
      # self.n=0
      self.name=name
      self.age=age

    def say(self):
      print('%s says welcome to the oldboy to learn Python' %self.name)
    # def __new__(cls, *args, **kwargs):
    #     print('OldboyTeacher.__new__')
    obj=OldboyTeacher('egon',18)
    print(obj.n)

    print(OldboyTeacher.n)

    call控制类的调用
    class Foo:
      def __call__(self, *args, **kwargs):
          print('================>')
          print(self)
          print(args)
          print(kwargs)


    obj1 = Foo()
    obj1(1,2,3,a=1,b=2) # 调用对象其实就是在调用对象类中定义的绑定方法__call__
    #

    # obj2 = int(10)

    # obj2()

    # obj3 = list([1, 2, 3])

    # obj3()
    每天逼着自己写点东西,终有一天会为自己的变化感动的。这是一个潜移默化的过程,每天坚持编编故事,自己不知不觉就会拥有故事人物的特质的。 Explicit is better than implicit.(清楚优于含糊)
  • 相关阅读:
    关于jsp
    NASA: A Closer View of the Moon(近距离观察月球)
    NASA: Seeing Jupiter(注视木星)
    NASA: SpaceX的猎鹰9号火箭将龙飞船发射到国际空间站
    导航狗IT周报第十五期(July 8, 2018)
    导航狗IT周报-2018年05月27日
    导航狗IT周报-2018年05月18日
    小苹果WP(实验吧-隐写术)
    Python实现猜数字游戏1.0版
    代码方式设置WordPress内所有URL链接都在新标签页打开
  • 原文地址:https://www.cnblogs.com/kylin5201314/p/13523913.html
Copyright © 2020-2023  润新知