zoukankan      html  css  js  c++  java
  • Python的元编程案例

                  Python的元编程案例

                                          作者:尹正杰

    版权声明:原创作品,谢绝转载!否则将追究法律责任。

    一.什么是元编程

      元编程概念来自LISP和smalltalk。 

      我们写程序是直接写代码,是否能够用代码来生成未来我们需要的代码吗?这就是元编程。
      例如,我们写一个类class A,能否用代码生成一个类出来?

      用来生成代码的程序称为元程序metaprogram,编写这种程序就称为元编程metaprogramming。
      Python语言能够通过反射实现元编程。   
      Python中所有非object类都继承自object类 所有类的类型包括type类都是type type类继承自object类,object类的类型也是type类

    二.type类

    1>.查看type的构造方法

    2>.使用type构造一个新类型(可以借助type构造任何类,用代码来生成代码,这就是元编程) 

     1 #!/usr/bin/env python
     2 #_*_conding:utf-8_*_
     3 #@author :yinzhengjie
     4 #blog:http://www.cnblogs.com/yinzhengjie
     5 
     6 def __init__(self,name,age):
     7     self.name = name
     8     self.age = age
     9 
    10 def show(self):
    11     print(self.__dict__)
    12 
    13 student = type("Student",(object,),{"school_address":"北京","__init__":__init__,"show":show})
    14 
    15 print(student)
    16 print(student.__dict__)
    17 print(student.__base__)
    18 print(student.mro())
    19 
    20 student("jason",18).show() 
    <class '__main__.Student'>
    {'school_address': '北京', '__init__': <function __init__ at 0x1006a2e18>, 'show': <function show at 0x10215fae8>, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}
    <class 'object'>
    [<class '__main__.Student'>, <class 'object'>]
    {'name': 'jason', 'age': 18}
    以上代码执行结果戳这里

     

    三.使用type构建元类

    1>.参考案例

     1 #!/usr/bin/env python
     2 #_*_conding:utf-8_*_
     3 #@author :yinzhengjie
     4 #blog:http://www.cnblogs.com/yinzhengjie
     5 
     6 #一个类可以继承自type类。注意不是继承自object类了。只要元类是ModelMeta,创建类对象时,就会调用ModelMeta的__new__方法
     7 class ModelMeta(type):
     8     def __new__(cls, name,bases,dict):
     9         print(name)
    10         print(bases)
    11         print(dict,"======")
    12         return super().__new__(cls,name,bases,dict)
    13 
    14 #继承自type,ModelMeta就是元类,它可以创建出其它类。
    15 class A(metaclass=ModelMeta):
    16     id = 1000
    17     def __init__(self):
    18         print("A.__init__")
    19 
    20 print("{0} 1 我是分割线 {0}".format("*" * 15))
    21 
    22 #第二种 B继承自A后,依然是从ModelMeta的类型
    23 class B(A):
    24     def __init__(self):
    25         print("B.__init__")
    26 
    27 print("{0} 2 我是分割线 {0}".format("*" * 15))
    28 #第三种 元类就可以使用下面的方式创建新的类
    29 p = ModelMeta("Person",(B,),{})
    30 
    31 #D、E是type的实例
    32 class D:pass        #等效于 D = type("D",(),{})
    33 E = type("E",(),{})
    34 
    35 #F是元类
    36 class F(ModelMeta):pass
    37 
    38 print("{0} 3 我是分割线 {0}".format("*" * 15))
    39 
    40 print(type(A),A.__bases__)
    41 print(type(B),B.__bases__)
    42 print(type(p),p.__bases__)
    43 
    44 print("{0} 4 我是分割线 {0}".format("*" * 15))
    45 print(type(D),D.__bases__)
    46 print(type(E),E.__bases__)
    47 print(type(F),F.__bases__)
    A
    ()
    {'__module__': '__main__', '__qualname__': 'A', 'id': 1000, '__init__': <function A.__init__ at 0x10195fae8>} ======
    *************** 1 我是分割线 ***************
    B
    (<class '__main__.A'>,)
    {'__module__': '__main__', '__qualname__': 'B', '__init__': <function B.__init__ at 0x10195fb70>} ======
    *************** 2 我是分割线 ***************
    Person
    (<class '__main__.B'>,)
    {} ======
    *************** 3 我是分割线 ***************
    <class '__main__.ModelMeta'> (<class 'object'>,)
    <class '__main__.ModelMeta'> (<class '__main__.A'>,)
    <class '__main__.ModelMeta'> (<class '__main__.B'>,)
    *************** 4 我是分割线 ***************
    <class 'type'> (<class 'object'>,)
    <class 'type'> (<class 'object'>,)
    <class 'type'> (<class '__main__.ModelMeta'>,)
    以上代码执行结果戳这里

    2>. 元类的应用

     1 class Field:
     2     def __init__(self, fieldname=None, pk=False, null=False):
     3         self.fieldname = fieldname
     4         self.pk = pk
     5         self.null = null
     6 
     7     def __repr__(self):
     8         return "<Field {} {} {}>".format(
     9             self.fieldname,
    10             self.pk,
    11             self.null
    12         )
    13 
    14 class ModelMeta(type):
    15     def __new__(cls, name, bases, attrs:dict):
    16         print('M ~~~~~~~~')
    17         print(cls)
    18         print(name, bases, attrs)
    19         if not hasattr(attrs, 'db_table'):
    20             attrs['db_table'] = name.lower()
    21         primarykeys = []
    22         for k, v in attrs.items():
    23             if isinstance(v, Field):
    24                 if not v.fieldname or v.fieldname.strip() == '':
    25                     v.fieldname = k # 字段没有名字使用属性名 if v.pk:
    26                     primarykeys.append(v)
    27         attrs['__primarykeys__'] = primarykeys
    28         return super().__new__(cls, name, bases, attrs)
    29 
    30 class Model(metaclass=ModelMeta):
    31     """从Model继承的类的类型都是ModelMeta"""
    32 
    33 
    34 class Student(Model):
    35     id = Field(pk=True, null=False)
    36     name = Field('username', null=False)
    37     age = Field()
    38 
    39 print("{0} 我是分割线 {0}".format("*" * 15))
    40 print(Student.__dict__)
    M ~~~~~~~~
    <class '__main__.ModelMeta'>
    Model () {'__module__': '__main__', '__qualname__': 'Model', '__doc__': '从Model继承的类的类型都是ModelMeta'}
    M ~~~~~~~~
    <class '__main__.ModelMeta'>
    Student (<class '__main__.Model'>,) {'__module__': '__main__', '__qualname__': 'Student', 'id': <Field None True False>, 'name': <Field username False False>, 'age': <Field None False False>}
    *************** 我是分割线 ***************
    {'__module__': '__main__', 'id': <Field id True False>, 'name': <Field username False False>, 'age': <Field age False False>, 'db_table': 'student', '__primarykeys__': [<Field id True False>, <Field age False False>], '__doc__': None}
    以上代码执行结果戳这里

    四.元编程总结

      元类是制造类的工厂,是用来构造类的类。 构造好元类,就可以在类定义时,使用关键字参数metaclass指定元类,可以使用最原始的 metatype(name, bases, dict)的方式构造一个类。
    
      元类的
    __new__() 方法中,可以获取元类信息、当前类、基类、类属性字典。
      元编程一般用于框架开发中。
      开发中除非你明确的知道自己在干什么,否则不要随便使用元编程
    99%的情况下用不到元类,可能有些程序员一辈子都不会使用元类   Django、SQLAlchemy使用了元类,让我们使用起来很方便。
  • 相关阅读:
    跟小静学CLR via C#(12)委托Delegate
    跟小静读CLR via C#(02)基元类型、引用类型、值类型
    跟小静读CLR via C#(07)静态类,分部类
    jQuery折叠菜单
    ajax调用后台Datatable
    跟小静读CLR via C#(11)无参属性、索引器
    跟小静读CLR via C#(08)操作符
    跟小静读CLR via C#(05) 访问限定、数据成员
    AjaxPro排错指南
    跟小静读CLR via C#(14)可空值类型,关于?和??的故事
  • 原文地址:https://www.cnblogs.com/yinzhengjie/p/11925664.html
Copyright © 2011-2022 走看看