元类是类的类,是类的模板
元类是用来控制如何创建类的,正如类是创建对象的模板一样,而元类的主要目的是为了控制类的创建行为

exec

  1. # 可以把exec命令的执行当成是一个函数的执行,会将执行期间产生的名字存放于局部名称空间中
  2. g = {
  3. 'x': 1,
  4. 'y': 2
  5. }
  6. l = {}
  7. exec('''
  8. global x,z
  9. x=100
  10. z=200
  11. m=300
  12. ''', g, l)
  13. print(g.get('y')) # {'x': 100, 'y': 2,'z':200,......}
  14. print(l) # {'m': 300}

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

  1. # 类也是对象,Foo=type(....)
  2. class Foo:
  3. pass
  4. obj = Foo()
  5. print(type(obj)) # <class '__main__.Foo'>
  6. print(type(Foo)) # <class 'type'>

创建类的两种方式

  1. # 方式一:class
  2. class Chinese: # Chinese=type(...)
  3. country = 'China'
  4. def __init__(self, namem, age):
  5. self.name = namem
  6. self.age = age
  7. def talk(self):
  8. print('%s is talking' % self.name)
  9. # print(Chinese)
  10. obj = Chinese('ecithy', 18)
  11. print(obj, obj.name, obj.age)
  1. # 方式二:type
  2. # 定义类的三要素:类名,类的基类们,类的名称空间
  3. class_name = 'Chinese'
  4. class_bases = (object,)
  5. class_body = """
  6. country='China'
  7. def __init__(self,namem,age):
  8. self.name=namem
  9. self.age=age
  10. def talk(self):
  11. print('%s is talking' %self.name)
  12. """
  13. class_dic = {}
  14. exec(class_body, globals(), class_dic)
  15. # print(class_dic)
  16. Chinese1 = type(class_name, class_bases, class_dic)
  17. # print(Chinese1)
  18. obj1 = Chinese1('egon', 18)
  19. print(obj1, obj1.name, obj1.age)

元类控制类

  1. class Mymeta(type):
  2. def __init__(self, class_name, class_bases, class_dic):
  3. if not class_name.istitle():
  4. raise TypeError('类名的首字母必须大写')
  5. if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
  6. raise TypeError('必须有注释,且注释不能为空')
  7. super().__init__(class_name, class_bases, class_dic)
  8. class Chinese(object, metaclass=Mymeta): 默认 metaclass=type
  9. '''
  10. 中文人的类
  11. '''
  12. country = 'China'
  13. def __init__(self, name, age):
  14. self.name = name
  15. self.age = age
  16. def talk(self):
  17. print('%s is talking' % self.name)
  18. people = Chinese('ecithy', 18)
  19. print(people.name)

元类控制类的实例化

语法

  1. class Mymeta(type):
  2. def __init__(self, class_name, class_bases, class_dic):
  3. if not class_name.istitle():
  4. raise TypeError('类名的首字母必须大写')
  5. if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
  6. raise TypeError('必须有注释,且注释不能为空')
  7. super(Mymeta, self).__init__(class_name, class_bases, class_dic)
  8. def __call__(self, *args, **kwargs): # obj=Chinese('ecithy',age=18)
  9. # 第一件事:先造一个空对象obj
  10. obj = object.__new__(self)
  11. # 第二件事:初始化obj
  12. self.__init__(obj, *args, **kwargs)
  13. # 第三件事:返回obj
  14. return obj
  15. class Chinese(object, metaclass=Mymeta):
  16. '''
  17. 中国人的类
  18. '''
  19. country = 'China'
  20. def __init__(self, name, age):
  21. self.name = name
  22. self.age = age
  23. def talk(self):
  24. print('%s is talking' % self.name)
  25. obj = Chinese('ecithy', age=18) # Chinese.__call__(Chinese,'ecithy',18)

应用

单例模式

  1. # 实现方式一:
  2. class MySQL:
  3. __instance = None # __instance=obj1
  4. def __init__(self):
  5. self.host = '127.0.0.1'
  6. self.port = 3306
  7. @classmethod
  8. def singleton(cls):
  9. if not cls.__instance:
  10. obj = cls()
  11. cls.__instance = obj
  12. return cls.__instance
  13. def conn(self):
  14. pass
  15. def execute(self):
  16. pass
  17. obj1 = MySQL.singleton()
  18. obj2 = MySQL.singleton()
  19. obj3 = MySQL.singleton()
  20. print(obj1 is obj3) # True
  1. # 实现方式二:元类的方式
  2. class Mymeta(type):
  3. def __init__(self, class_name, class_bases, class_dic):
  4. if not class_name.istitle():
  5. raise TypeError('类名的首字母必须大写')
  6. if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
  7. raise TypeError('必须有注释,且注释不能为空')
  8. super().__init__(class_name, class_bases, class_dic)
  9. self.__instance = None
  10. def __call__(self, *args, **kwargs): # obj=Chinese('egon',age=18)
  11. if not self.__instance:
  12. obj = object.__new__(self)
  13. self.__init__(obj)
  14. self.__instance = obj
  15. return self.__instance
  16. class Mysql(object, metaclass=Mymeta):
  17. '''
  18. mysql xxx
  19. '''
  20. def __init__(self):
  21. self.host = '127.0.0.1'
  22. self.port = 3306
  23. def conn(self):
  24. pass
  25. def execute(self):
  26. pass
  27. obj1 = Mysql()
  28. obj2 = Mysql()
  29. obj3 = Mysql()
  30. print(obj1 is obj2 is obj3) # True