zoukankan      html  css  js  c++  java
  • Python-元编程

    1、元编程:

      元编程 概念来自 LISP 和 smalltalk

      我们写程序 是直接写代码,是否能够用代码来生成未来我们需要的代码,这就是元编程。

      用阿里生成代码的程序称为元程序,metaprogram,编写这种程序就称为元编程。

      Python 语言能够通过反射实现 元编程

      

      python 中;

        所有非object 类都继承自object 类

        所有类的类型包括 type类 都是type

        type类 继承自object 类,object类的类型也是type类

    2、type类

      type构建类: 

    1 class type(object):
    2     """
    3     type(object_or_name, bases, dict)
    4     type(object) -> the object's type  ----> 返回对象的类型,例如 type(10)
    5     type(name, bases, dict) -> a new type ----> 返回一个新的类型
    6     """

      测试:

    1 XClass = type('mycalss', (object,), {'a':100, 'b':'string'})
    2 
    3 print(XClass)
    4 print(XClass.__dict__)
    5 print(XClass.__name__)
    6 print(XClass.__bases__)
    7 print(XClass.mro())

      结果:

    <class '__main__.mycalss'>
    {'a': 100, 'b': 'string', '__module__': '__main__', '__dict__': <attribute '__dict__' of 'mycalss' objects>, '__weakref__': <attribute '__weakref__' of 'mycalss' objects>, '__doc__': None}
    mycalss
    (<class 'object'>,)
    [<class '__main__.mycalss'>, <class 'object'>]

       mycalss 是创建类的 标识符

      (objects,): 基类

      类似命名元组

      

      测试:

     1 def __init__(self):
     2     self.x = 100
     3 
     4 def show(self):
     5     print(self.__dict__)
     6     print(self.x)
     7 
     8 XClass = type('myclass', (object,), {'a':100,'b':111, 'show':show, '__init__':__init__})
     9 
    10 print(XClass)
    11 print(XClass.__name__)
    12 print(XClass.__dict__)
    13 print(XClass.mro())
    14 
    15 print('-' * 40)
    16 XClass().show()

      结果:

    1 <class '__main__.myclass'>
    2 myclass
    3 {'a': 100, 'b': 111, 'show': <function show at 0x00000000023322F0>, '__init__': <function __init__ at 0x00000000004BC1E0>, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'myclass' objects>, '__weakref__': <attribute '__weakref__' of 'myclass' objects>, '__doc__': None}
    4 [<class '__main__.myclass'>, <class 'object'>]
    5 ----------------------------------------
    6 {'x': 100}
    7 100

      可以借助type 构造 任何类,用代码来生成代码,这就是元 编程

    3、构造元类:

      一个类可以继承自type 类,注意不是继承自 object 类了。

     1 class ModelMeta(type):
     2     def __new__(cls, *args, **kwargs):
     3         print(cls)
     4         print(args) # 就是 type(name,bases, dict)的参数
     5         print(kwargs)
     6         print('------------------------------')
     7         return super().__new__(cls, *args, **kwargs)
     8 # 此处的 ModelMeta 就是元类,继承自type,它可以创建出其他类
     9 
    10 # 第一种 使用metaclass 关键字 参数指定元类
    11 class A(metaclass=ModelMeta):
    12     id = 100
    13 
    14     def __init__(self):
    15         print(' ==== A ====')
    16 print(A.__class__)
    17 print(A.mro())
    18 print('~~~~~~~~~~~~~~====~~~~~~~~~~')
    19 # 第二种 B继承自 A 后,依然是从ModelMeata的类型
    20 class B(A):
    21     def __init__(self):
    22         print('==== B ====')
    23 
    24 print(B.__class__)
    25 print(B.mro())
    26 print('~~~~~~~~~~~~====~~~~~~~~~~~~')
    27 # 第三种 元类就可以使用下面的方式创建新的类
    28 C = ModelMeta('C', (), {})
    29 print(C.__class__)
    30 print(C.mro())
    31 print('~~~~~~~~~~~~====~~~~~~~~~~~~')
    32 
    33 # D,E 是type的 实例, 没有使用自定义的元类,所以默认使用type
    34 class D:pass
    35 E = type('E', (), {})
    36 
    37 class F(ModelMeta):pass # 和A  不一样,没有使用关键字 metaclass
    38 
    39 print('=============================')
    40 print(type(A), A.__bases__)
    41 print(type(B), B.__bases__)
    42 print(type(C))
    43 print(type(D))
    44 print(type(E))
    45 print(type(F), F.__bases__)

      结果:

     1 D:python3.7python.exe E:/code_pycharm/test_in_class/tt14.py
     2 <class '__main__.ModelMeta'>
     3 ('A', (), {'__module__': '__main__', '__qualname__': 'A', 'id': 100, '__init__': <function A.__init__ at 0x00000000029422F0>})
     4 {}
     5 ------------------------------
     6 <class '__main__.ModelMeta'>
     7 [<class '__main__.A'>, <class 'object'>]
     8 ~~~~~~~~~~~~~~====~~~~~~~~~~
     9 <class '__main__.ModelMeta'>
    10 ('B', (<class '__main__.A'>,), {'__module__': '__main__', '__qualname__': 'B', '__init__': <function B.__init__ at 0x0000000002942378>})
    11 {}
    12 ------------------------------
    13 <class '__main__.ModelMeta'>
    14 [<class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
    15 ~~~~~~~~~~~~====~~~~~~~~~~~~
    16 <class '__main__.ModelMeta'>
    17 ('C', (), {})
    18 {}
    19 ------------------------------
    20 <class '__main__.ModelMeta'>
    21 [<class '__main__.C'>, <class 'object'>]
    22 ~~~~~~~~~~~~====~~~~~~~~~~~~
    23 =============================
    24 <class '__main__.ModelMeta'> (<class 'object'>,)
    25 <class '__main__.ModelMeta'> (<class '__main__.A'>,)
    26 <class '__main__.ModelMeta'>
    27 <class 'type'>
    28 <class 'type'>
    29 <class 'type'> (<class '__main__.ModelMeta'>,)
    30 
    31 Process finished with exit code 0

      修改代码如下:

     1 class ModelMeta(type):
     2     def __new__(cls, name, bases, dict):
     3         print(cls)
     4         print(name)
     5         print(dict)
     6         print('------------------------------')
     7         return super().__new__(cls, name, bases, dict)
     8 # 此处的 ModelMeta 就是元类,继承自type,它可以创建出其他类
     9 
    10 # 第一种 使用metaclass 关键字 参数指定元类
    11 class A(metaclass=ModelMeta):
    12     id = 100
    13 
    14     def __init__(self):
    15         print(' ==== A ====')

       从结果看出,只要元类是ModelMeta,创建类对象时,就会调用MoelMeta的 __new__方法

    元类的应用:

      模拟创建表格式

     1 class Field:# 定义字段的属性类
     2     def __init__(self, fieldname=None,pk=False, nullable=True):
     3         self.fieldname= fieldname
     4         self.pk = pk
     5         self.nullable = nullable
     6 
     7     def __repr__(self):
     8         return '<Field {}'.format(self.fieldname)
     9 
    10 class ModelMeta(type):
    11     def __new__(cls, name, bases, attrs:dict):
    12         print(cls)
    13         print(name)
    14         print(bases)
    15         print('=====', attrs,'=====')
    16 
    17         if '__tablename__' not in attrs.keys():
    18             attrs['__tablename__'] = name
    19 
    20         primarykey = []
    21         for k, v in attrs.items():
    22             if isinstance(v, Field):
    23                 if v.fieldname is None:
    24                     v.fieldname = k
    25                 if v.pk:
    26                     primarykey.append(v)
    27         attrs['__primarykey__'] = primarykey
    28 
    29         return super().__new__(cls, name, bases, attrs)
    30 
    31 class ModelBase(metaclass=ModelMeta):
    32     ''' 从 ModelBases 继承的类的类型都是ModelMeta '''
    33     pass
    34 
    35 class Students(ModelBase):
    36     id = Field(pk=True, nullable = False)
    37     name = Field('username', nullable=False)
    38     age = Field()
    39 
    40 print('====================================')
    41 print(Students.__dict__)

      结果:

     1 D:python3.7python.exe E:/code_pycharm/test_in_class/tt14.py
     2 <class '__main__.ModelMeta'>
     3 ModelBase
     4 ()
     5 ===== {'__module__': '__main__', '__qualname__': 'ModelBase', '__doc__': ' 从 ModelBases 继承的类的类型都是ModelMeta '} =====
     6 <class '__main__.ModelMeta'>
     7 Students
     8 (<class '__main__.ModelBase'>,)
     9 ===== {'__module__': '__main__', '__qualname__': 'Students', 'id': <Field None, 'name': <Field username, 'age': <Field None} =====
    10 ====================================
    11 {'__module__': '__main__', 'id': <Field id, 'name': <Field username, 'age': <Field age, '__tablename__': 'Students', '__primarykey__': [<Field id], '__doc__': None}
    12 
    13 Process finished with exit code 0
    View Code

    元编程总结:

      元类是制造类的工厂,是生成类的类

      构造好元类,就可以在类定义的时候,使用关键字参数 metaclass 指定元类,可以使用最原始的metatype(name,base,dict)的方式 构造一个类

      元类的__new__()方法中,可以获取元类的信息,当前类,基类,类属性字典

      

      元编程一般用于框架开发中,Django SQLAlchemy 都使用了 元类。

    为什么要坚持,想一想当初!
  • 相关阅读:
    【NOIP2007】守望者的逃离
    20200321(ABC)题解 by 马鸿儒 孙晨曦
    20200320(ABC)题解 by 王一帆
    20200319(ABC)题解 by 王一帆 梁延杰 丁智辰
    20200314(ABC)题解 by 董国梁 蒋丽君 章思航
    20200309(ABC)题解 by 梁延杰
    20200307(DEF)题解 by 孙晨曦
    20200306(ABC)题解 by 孙晨曦
    20200305(DEF)题解 by 孙晨曦
    20200303(ABC)题解 by 王锐,董国梁
  • 原文地址:https://www.cnblogs.com/JerryZao/p/9938976.html
Copyright © 2011-2022 走看看