You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

121 lines
3.6KB

  1. # -*- coding: utf-8 -*-
  2. class Test:
  3. pass
  4. print(type(Test))
  5. print(type(int))
  6. # 结果都为<class 'type'>,type就是内置的元类,class关键字定义的所有的类以及内置的类都是由元类type实例化产生。
  7. """
  8. 由于在python3中没有经典类和新式类的区别,因此python3中object是所有类的基类,那内置元类type又是什么?
  9. type是object类的类型,总结来说就是type是object的类型,同时,object又是type的基类,这句话看起来就有问题,
  10. 到底是先有type还是先有object呢?这个问题有点类似于先有鸡还是先有蛋,我们可以通过代码简单分析一下
  11. 在python3中类和类型是同一种东西,因此对象.__class__和type(对象)得到的结果是一致的,object的基类为空,
  12. 但是type的基类为object,但是object的类型又是type。
  13. """
  14. print(type(object))
  15. print(object.__class__)
  16. print(type(type))
  17. print(type.__class__)
  18. print(object.__bases__)
  19. print(type.__bases__)
  20. # python字符串
  21. strs = """
  22. global name
  23. global age
  24. name = 'py'
  25. age = 18
  26. addr = 'xx'
  27. """
  28. # 定义全局作用域中的名字和值
  29. globals = {
  30. 'a': '1',
  31. 'b': '2'
  32. }
  33. # 定义局部作用域中的名字和值
  34. locals = {
  35. 'x': 3,
  36. 'y': 4
  37. }
  38. exec(strs, globals, locals)
  39. print(globals['name'])
  40. print(locals)
  41. # 了解了exec的作用之后,就可以分析class关键字如何借助type元类产生类的步骤:
  42. # 1 定义类名
  43. class_name = 'Test'
  44. # 2 定义类的基类(父类)
  45. class_bases = (object,)
  46. # 3 执行类体代码拿到类的名称空间
  47. class_dic = {}
  48. # 4 定义类体代码(本质是字符串)
  49. class_body = """
  50. def __init__(self,name,age):
  51. self.name=name
  52. self.age=age
  53. def test(self):
  54. print('%s:%s' %(self.name,self.name))
  55. """
  56. # 5 将字符串转为python能识别的语法:将class_body运行时产生的名字存入class_dic中
  57. exec(class_body, {}, class_dic)
  58. # 查看类的名称空间
  59. print(class_dic)
  60. # 6 调用元类产生类
  61. Test = type(class_name, class_bases, class_dic)
  62. # 7 调用类产生对象
  63. t = Test('python', '12')
  64. t.test()
  65. # 自定义元类
  66. class MyMeta(type): # 自定义元类必须继承type,否则就是普通的类
  67. '''
  68. 早于__init__方法执行,必须返回空对象,由于该方法是调用类后第一个运行的方法,
  69. 此时并没有对象产生,因此该方法的第一个参数必须是类本身(MyMeta),*args, **kwargs
  70. 用来接收调用元类产生对象所需的参数(类名 类的基类 名称空间)
  71. '''
  72. def __new__(cls, *args, **kwargs):
  73. return type.__new__(cls, *args, **kwargs) # 直接调用父类type中的__new__方法
  74. '''
  75. 通过__init__控制类的产生,调用自定义元类与调用内置元类type的方式相同,
  76. 需要传入类名、类的父类们、类体代码的名称空间,__init__方法中第一个参数来自于__new__方法产生的空对象。
  77. '''
  78. def __init__(self, class_name, class_bases, class_dict):
  79. '''
  80. 在该方法内可以控制类的产生
  81. '''
  82. if not class_name.istitle(): # 实现类名首字母必须大写,否则抛出异常
  83. raise NameError('类名的首字母必须大写')
  84. if '__doc__' not in class_dict or len(class_dict['__doc__'].strip())==0: # 实现类必须有文档注释,否则抛出异常
  85. raise TypeError('必须有文档注释')
  86. def __call__(self, *args, **kwargs):
  87. print(self)
  88. print(args)
  89. print(kwargs)
  90. return 'test'
  91. class Test(metaclass=MyMeta):
  92. '''
  93. 我是文档注释
  94. '''
  95. def __init__(self):
  96. self.name = 'python'
  97. def test(self):
  98. print('test')
  99. t = Test()