元类是Python中一种神奇的特性,可以实现像魔法一样的效果,要理解元类,首先要先理解Python的类.Python中一切都是对象,包括类,他们的关系:
我们最常用到的元类就是奇妙的type,一般情况下,type被用来检测某个对象的类型,比如:
>>>type(1)
<class 'int'>
>>>type("a")
<class 'str'>
>>>type("true")
<class 'bool'>
那么类的类是什么?
class Class:
pass
print(type(Class)) #是什么?
# <class 'type'>
是的,是type!所以我们也可以用type来创建类.虽然所有人都知道,用同一个函数仅仅传入不同的参数就实现完全不同的功能,是非常愚蠢的做法.但Python这么做是为了向后兼容,所以似乎也没什么可指责的.type的定义:
def type(name:str,base:tuple,namespace:dict)->type:pass
#name:类名
#bases:继承的类
#namespace:类属性,注意不是实例属性
正常的类都是由type创建出来的,但我们也可以创建自己的元类,让他继承自type,并设定某个类使用它.而这个类的子类也就同样是这个元类产生出的类.一个基本的元类如下:
class MetaClass(type):
def __new__(cls,name,bases,namespace):
#执行操作...
#其实下面那行也可以改成return type(name,bases,namespace),但这样保持了代码的一致性.
return super().__new__(cls,name,bases,namespace)
@classmethod
def __prepare__(cls,name,bases,**kwargs):
return super().__prepare__(name,bases,**kwargs)
def __init__(self,name,bases,namespace,**kwargs):
#执行操作,注意这里虽然是self,但其实就是指我们的类,因为这个类的实例是类
return super().__init__(name,bases,namespace,**kwargs)
def __call__(self,*args,**kwargs):
return super().__call__(*args,**kwargs)
有了元类,我们就要把它应用到正常的类中,这里介绍Python3的语法,Python2因为已经有些过时这里就不在说了.语法:
class Class(metaclass=MetaClass):
pass
这样我们就拥有了一个以我们自己的元类为元类创建出来的类了.元类可以为我们的类添加很多神奇的功能.比如说,如果不使用元类,很难想象Django的ORM,也就是Django的Model部分是如何实现的.当然大家都会说,Django并没有让你在Class的括号里写metaclass,很简单,当一个类使用了我们自己定义的元类后,它的子类也会使用它,比如说,我们接下来再定义一个ChildClass:
class ChildClass(Class):
pass
运行后会发现,它使用的同样是我们的元类,而不是默认的type.
最后,再次提醒一遍,除非是为了做框架,或者为了学习Python中神妙的特性,否则不要在你的项目中使用元类.它会让那些不了解你底层实现的人十分困惑.
(元类)是深奥的知识,99%的用户都无须关注,如果你想知道是否需要使用元类,我告诉你,不需要(真正需要使用的人确信他们需要,无需解释原因)
——Tim Peter(Timsort排序算法发明者)
以上是这篇文章的全部,错误的地方恳请指正.
希望能和大家一起学习.
最后,都看到这了,赞赏一下呗!(^ ~ ^||).