元类

元类

元类的定义

  元类其实就是产生类的类,需要注意的是,元类和父类有非常大的不同。

  • 父类与子类是在面向对象的继承中的定义。通过继承子类能够使用父类的数据和方法
  • 元类是在类的产生阶段的概念。只有产生类的类才能称为元类
  • 元类不能直接通过继承的方式指定

元类的引入

  在学习数据类型的时候,关键字type的作用是查看数据类型。

      print(type('oliver'))  # <class 'str'>
      print(type(25))  # <class 'int'>
      print(type({'name': 'oliver', 'age': 25}))  # <class 'dict'>
      print(type(['oliver', 25]))  # <class 'list'>

  学习面向对象编程以后,我们知道python中可以说是万物皆对象。自然而然,数据和类都应该是对象。根据查看数据类型的过里的<class 'str'>里面的class,我们大概能知道str其实是一个类名。而这里查看的其实也不是数据类型,而是产生该对象的类。如果把关键字type括号里的数据看做对象的话,也可以把类名当做对象放进此处。

      class Person:
          pass

      class People:
          pass

      class Human:
          pass


      print(type(Person))  # <class 'type'>
      print(type(People))  # <class 'type'>
      print(type(Human))  # <class 'type'>

  根据结果<class 'type'>可以发现,产生类(对象)的类其实是类type。这里的类type是Python中的默认元类。另外元类是可以通过一些特殊的方法进行指定的。

创建类的方式

方式一:class关键字

    class C1(object):
        pass
    print(C1)  # <class '__main__.C1'>

方式二:type(类名, 父类, 类的名称空间)

      print(type('C1', (), {}))  # <class '__main__.C1'>

  以上两种方式创建类的方式的结果其实是一样的。

元类进阶

定义元类的作用

  元类能够创建类,也就意味着我们可以通过编写元类的类体代码对所要创建的类进行定制(添加一些创建类的条件)

元类的使用与指定

      class MyClass():
          pass
      print(type(MyClass))  # <class 'type'>

      class A(MyClass):
          pass
      print(type(A))  # <class 'type'>

  继承MyClass以后,类A的元类依然是类type。也就是说,类继承父类只是能够调用父类的方法,而不是由父类创建。而是通过关键字参数metaclass=元类名指定的

      class MyClass():
          pass
      print(type(MyClass))  # <class 'type'>

      class A(metaclass=MyClass):
          pass
      print(type(A))  # <class '__main__.MyClass'>

元类如何创建定制的类

  • 类创建对象的过程中可以在类的__init__方法内进行对象的实例化
  • 元类创建类(类也是对象)的时候也可以在元类的__init__方法内进行定制
      class MyClass(type):
          def __init__(cls, cls_name, cls_bases, cls_dict):
              if cls_name.istitle():  # 判断类名是否首字母大写、其余字母小写
                  if len(cls_name) < 6:  # 限制类名长度
                      super().__init__(cls_name, cls_bases, cls_dict)
                  else:
                      raise Exception('类名长度必须小于6')
              else:
                  raise Exception('类名首字母未大写')
      print(type(MyClass))  # <class 'type'>
      class Amy(metaclass=MyClass):
          pass
      print(Amy)
      class amy(metaclass=MyClass):
          pass  # Exception: 类名首字母未大写
      class Amy_City(metaclass=MyClass):
          pass  # Exception: 类名长度必须小于6
      print(type(Amy))  # <class '__main__.MyClass'>

__call__方法

  __call__方法: 在对象加括号调用时,自动执行产生该对象的类里的__call__方法,并获取__call__方法的返回值。
  __call__方法执行流程:
     1. 产生空对象(其实是调用__new__方法)
     2. __init__实例化对象
     3. 返回对象

      class MyClass(type):
          def __init__(cls, cls_name, cls_bases, cls_dict):
              if cls_name.istitle():  # 判断首字母是否大写,其余小写
                  if len(cls_name) < 6:  # 限制类名长度
                      super().__init__(cls_name, cls_bases, cls_dict)
                  else:
                      raise Exception('类名长度必须小于6')
              else:
                  raise Exception('类名首字母未大写')

          def __call__(self, *args, **kwargs):
              if args:  # 判断位置参数是否有位置参数
                  raise Exception('参数必须是关键字参数')
              else:
                  super().__call__(*args, **kwargs)  # 没有的时候执行元类的__call__方法
                  return self

      class beta_bbb(metaclass=MyClass):
          def __init__(self, b):
              self.b = b

      class A(metaclass=MyClass):
          def __init__(self, name):
              self.name = name

      obj1 = A(name='oliver')
      print(obj1.__dict__)
      print(obj1)  # <class '__main__.A'>


      class amy_city(metaclass=MyClass):
          def __init__(self, name):
              self.name = name

      obj1 = amy_city(name='oliver')
      print(obj1.__dict__)


      class Amycity(metaclass=MyClass):
          def __init__(self, name):
              self.name = name


      obj1 = Amycity(name='oliver')
      print(obj1.__dict__)

      class Century(metaclass=MyClass):
          def __init__(self, c):
              self.c = c

__new__方法

'''
      __new__ 产生空对象        名称空间空的
      __init__ 实例化对象       添加数据进入名称空间
'''
      class MyClass(type):
          def __new__(cls, *args, **kwargs):
              print('__new__ 执行')  # __new__ 执行  产生空对象
              return super().__new__(cls, *args, **kwargs)

          def __init__(cls, cls_name, cls_bases, cls_dict):
              print('__init__ 执行')  # __init__ 执行  # 实例化对象
              super().__init__(cls_name, cls_bases, cls_dict)

      class Class(metaclass=MyClass):
          def __init__(self, name):
              self.name = name
              print('实例化对象的过程中执行')

      print(Class)

      a = Class('a')
      print(a)
posted @ 2022-04-11 23:26  Oliver-Chance  阅读(72)  评论(0编辑  收藏  举报