这篇文章主要介绍python中元类元类是什么,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!
元编程,一个听起来特别酷的词,强大的Lisp在这方面是好手,对于python,尽管没有完善的元编程范式,一些天才的开发者还是创作了很多元编程的魔法.Django的ORM就是元编程的一个很好的例子。
<强>一切都是对象强>
python里一切都是对象(<代码>对象> 代码),基本数据类型,如数字,字串,函数都是对象。对象可以由类(<代码>类> 代码)进行创建。既然一切都是对象,那么类是对象吗?
是的,类也是对象,那么又是谁创造了类呢?答案也很简单,也是类,一个能创作类的类,就像上帝一样,开启了万物之始。这样的类,称之为元类(<代码> classmeta> 代码)。
<强>类的定义强>
对象是通过类创建的,这个很好理解,例如下面的代码:
类酒吧(对象): 通过 酒吧=bar () 打印(酒吧,bar.__class__) # & lt; __main__。酒吧在0 x101eb4630>对象;& lt;类& # 39;__main__.Bar& # 39;比; 打印(酒吧,Bar.__class__) # & lt;类& # 39;__main__.Bar& # 39;比;& lt;类& # 39;类型# 39;在
可以看见对象酒吧是类酒吧创建的实例。然而酒吧,看起来却是由一个叫类型的类创建的实例。即<代码>栏& lt;——酒吧& lt;——类型代码>。
上面的例子,对象是动态创建的,类则是通过关键字类声明定义的. class关键字背后的玄机是什么呢?
实际上,<代码>类酒吧(对象)代码>这样的代码,等价于<代码>栏=类型(& # 39;酒吧# 39;(对象),{})代码>
即类类型通过实例化创建了它的对象酒吧,而这个酒吧恰恰是一个类。这样能创建类的类,就是Python的元类。
从创建酒吧的代码上来看,元类类型的<代码> __init__ 代码>方法有3个参数,
- <李>第一个是创建的类的名字李> <李>第二个是其继承父类的元类列表,李> <李>最后就是一个属性字典,即该类所具有的属性。
李,>
<>强类型元类强>
类型是小写,因而很容易误以为它是一个函数。通过帮助(类型)可以看到它的定义如下:
类类型(对象): “““ 类型(object_or_name、基地、dict类型) 类型(对象)→对象# 39;年代类型 类型(名称、基地、dict)→一种新型 “““ def __init__ (cls,基地=None, dict=None): # type.__init__的已知的特例 “““ 类型(object_or_name、基地、dict类型) 类型(对象)→对象# 39;年代类型 类型(名称、基地、dict)→一种新型 #(从类文档复制) “““ 通过 @staticmethod #已知__new__的案例 def __new__ (* args, * * kwargs): #真正的签名未知 “““创建并返回一个新的对象。看到帮助准确签名(类型)。“““ 通过
如前所述<代码>,__init__ 代码>方法接受三个参数,类型实例化的过程,会创建一个新的类。创建类的代码来自<代码> __new__ 代码>方法,它的参数其实和<代码> __init__> 代码,一样。至于它们之间有什么关系,后面再做介绍。目前只要知道,当调用类型进行实例化的时候,会先自动调用<代码> __new__ 代码>方法,然后再接着调用<代码> __init__ 代码>方法,在类外面来看,最终会实例化一个对象,这个对象是一个类。
从类型的定义来看,它继承对象,Python3的所有类,都继承来着对象,类类型也是对象的实例,令人奇怪的是,对象既是类也是对象,它也是由类型实例化而来,有一种鸡生蛋,蛋生鸡的悖论。暂且先不管,只要知道所有类的顶级继承来自对象就好。
<>强自定义元类
强>
既然元类可以创建类,那么自定义元类就很简单了,直接继承类类型即可。先看下面一个例子:
类MyType(类型): 通过 类酒吧(对象、元类=MyType): 通过 打印(MyType MyType.__class__) # & lt;类& # 39;__main__.MyType& # 39;比;& lt;类& # 39;类型# 39;比; 打印(酒吧,Bar.__class__) # & lt;类& # 39;__main__.Bar& # 39;比;& lt;类& # 39;__main__.MyType& # 39;在
可以看的到,酒吧在声明的时候,指定了其元类,此时的类Bar的<代码> __class__进行代码>属性不再是类型,而是MyType。即之前定义酒吧的代码不再是<代码>栏=类型(& # 39;酒吧# 39;(对象),{})> 代码,而是<代码>栏=MyType(& # 39;酒吧# 39;(对象),{})> 代码。创建的元类的代码是<代码> MyType=类型(& # 39;MyType& # 39;(对象),{})代码>。