Python神技-元类

元类是Python中一种神奇的特性,可以实现像魔法一样的效果,要理解元类,首先要先理解Python的类.Python中一切都是对象,包括类,他们的关系:


类的关系.png

我们最常用到的元类就是奇妙的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排序算法发明者)



以上是这篇文章的全部,错误的地方恳请指正.
希望能和大家一起学习.
最后,都看到这了,赞赏一下呗!(^ ~ ^||).

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容