Python全栈

29.Python之面向对象的元类

2020-03-14  本文已影响0人  免跪姓黄

Python之面向对象的元类

  1. 什么是元类?

    • 类的类就是元类,元类创建对象。使用class定义的类,用来产生程序员自己的对象;而class定义的类,是由内置的元类type产生的。

      class Chinese:  # 默认的元类是type
          country = 'China'
      
          def __init__(self, name, age, sex):
              self.name = name
              self.age = age
              self.sex = sex
      
    • 使用class定义类等同于使用以下方式定义类:

      class_name = 'Chinese'
      class_base = (object,)    # 基类为元组
      class_body = '''
      country = 'China'
      def __init__(self, name, age, sex):
      self.name = name
      self.age = age
      elf.sex = sex
      '''
      class_dic = {}
      exec(class_body, {}, class_dic)    # 产生类的名称空间
      
      # 类的三大要素,类名,基类,类的名称空间
      Chinese = type(class_name, class_base, class_dic)
      

  1. 为什么要有元类?

    • 控制类的创建和行为。

  1. 怎么样自定义元类?

    class MyMetaclass(type):  # 继承type并且可以派生
        def __init__(self, class_name, class_base, class_dic):  # self=Foo
            if not class_name.istitle():  # 可以控制创建类时名字的命名规范
                raise TypeError('类的名字必须首字母大写')
            if not class_dic.get('__doc__'):
                raise TabError('创建类必须写好描述信息')
            super(MyMetaclass, self).__init__(class_name, class_base, class_dic)
    
        def __call__(self, *args, **kwargs):
            # 当执行 Foo(1) 时会做以下事情:
            # 1.创造一个空对象obj
            obj = object.__new__(self)
            # 2.调用 Foo.__init__,并将obj连同Foo括号内的参数一同传给Foo.__init__(self.y)
            self.__init__(obj, *args, **kwargs)
            return obj
    
        pass
    
    
    class Foo(object,metaclass = MyMetaclass):  # 由于Python中一切皆对象,因此Foo是元类type实例化而来,默认实例化通过Foo=type('Foo',(object,),class_dic)完成,现在是Foo=MyMetaclass('Foo',(object,),class_dic)完成实例化
        '''
        描述信息
        '''
        x = 1
        
        def __init__(self, y):
            self.y = y
    
        def f(self):
            print('from f')
    
    
    print(Foo.__doc__)  # 查看类的描述信息
    
    Foo(1)
    

  1. 单例模式

    • 单个实例,节省内存,单例模式用在对象内存的数据属性是一样的情况下,就没必要开辟新的内存空间了,因此要使用单例模式节省内存。
上一篇下一篇

猜你喜欢

热点阅读