Python-元编程

Posted JerryZao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 都使用了 元类。

 

以上是关于Python-元编程的主要内容,如果未能解决你的问题,请参考以下文章

深刻理解Python中的元类(metaclass)

说说 Python 的元编程

说说 Python 的元编程

深刻理解Python中的元类(metaclass)

Python 元编程

深刻理解Python中的元类(metaclass)