zoukankan      html  css  js  c++  java
  • 面向对象之元类等相关内容-34

    元类

    # 一切源自于一句话: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)
    exec方法是将类体代码转换成字典的形式 参数为 类体代码、空字典、需要导出的字典
    # 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
    '''

    # 六:单例模式

    # settings
    HOST = "192.168.11.10"
    PORT = 3306

    # 实现方式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)
          self代表的是mysql类

      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)

     

  • 相关阅读:
    021.NET5_Autofac多种注入方式
    020.NET5_Autofac初识
    018-019 NET5_内置容器支持依赖注入+IServiceCollection的生命周期
    017.NET5_内置容器基本使用
    设计库和表从哪些方面考虑(MYSQL)
    MD5的如何加密空字符串的(PHP)
    Think php 5登陆注册session储存
    think php 5(命令行)创建控制器、model
    PHP面试题(个人总结)————(暂不更新)
    PHP中的curl库使用
  • 原文地址:https://www.cnblogs.com/usherwang/p/13530408.html
Copyright © 2011-2022 走看看