例如:
可以手动的这样创建:
你注意到我们使用’MyShinyClass’作为类的名称,同时作为变量保存这个类的引用。它们可以不一样,但是我们没有理由来将问题复杂化。
type接收一个字典来定义这个类的属性,所以:
也可以写成:
Foo = type(‘Foo’, (), {‘bar’:True})
然后可以当成正常的类来使用:
当然,你也可以继承它,如:
可以写成:
最后,如果你想为你的类添加方法,只需要定义一个有适当签名的函数,然后把它当成一个属性分配给它。
你甚至可以在你动态创建完类之后给它添加更多的方法,就像一个正常创建的类添加方法一样:
现在你应该明白:在Python中,类都是对象,你可以在运行时动态的创建一个类。 这就是当你使用关键字class的时候,Python所做的,而且是通过元类来做的。
什么是元类(metaclass)
元类就是创建类的’职工’。你定义类来达到创建对象的目的,对么?但是我们已经知道Python类都是对象。
好吧,元类就是用来创建这些类(对象)的,元类就是类的类,你可以这样想象它们:
你已经知道type可以帮你做这样的事情:
MyClass = type(‘MyClass’, (), {})
那是因为,事实上type函数就是一个元类,type就是Python用来在幕后创建所有类的元类。
现在,你可能会好奇,为什么type是小写的,而不是Type?
我猜测是因为为了保持一致性,就像str这个类用来创建所有的字符串对象,int用来创建所有的整数对象,type仅仅是用来创建类对象的类。
你可以通过查看class属性来看看。
所有的事情,在python中都是对象,包括ints, strings, functions和classes.所有的它们都是对象,所有的它们都是通过一个类创建的。
那,class__的__class是什么呢?
所以,元类仅仅是用来创建类的东西,你可以把它称之为’class factory’。 type是Python使用的内置的metaclass, 但是很正常,你可以创建你自己的元类。
metaclass 属性
当你定义个类的时候,可以添加一个metaclass属性。
如果你这么做,Python会使用这个metaclass来创建类Foo。小心,这个地方非常tricky。 你首先定义了class Foo(object),但是类对象Foo还没有在内存中创建。
Python会去查找类定义中的metaclass,如果它找到了,它就会创建这个对象类Foo。如果没有,它就会使用type来创建这个类。
多理解几遍。
当你创建一个类:
Python会做如下这些操作:
首先判定,在Foo中是否存在 __metaclass__属性? 如果存在,Python会在内存中通过__metaclass__创建一个名字为Foo的类对象。如果Foo中找不到__metaclass__,它会在MODULE级别查找__metaclass__,然后阐释做同样的事情。 如果它最终都没有找到任何的__metaclass__,它会使用它父类的metaclass来创建类对象。 需要注意的是,__metaclass__属性是不能够被继承的,父类的元类是可以被继承的。如果Bar使用一个__metaclass__属性通过type()来创建(不是通过type.new()),子类不会继承这个行为。
现在问题是,你可以放什么东西在metaclass中呢? 答案是:能够创建一个类的东西。 然而什么可以创建一个类呢?type,或者是其他子类,或者使用type。
自定义元类
元类的主要目的是当一个类创建的时候,能够自动的修改这个类。
当我们想创建一个匹配上线文信息的类的时候,我们平常都是通过API来处理。想想一个很傻的例子,当你决定你的模块中的所有的类的属性都应该是大写,有几种做法可以处理这样的事情,其中通过在模块级别设置__metaclass__可以达到目的。
这种方式,模块中所有的类会使用元类来创建,我们仅仅需要告诉元类把所有的属性修改成大写即可。
幸运的是,__metaclass__只要实际的能够调用就行,它不需要是一个正式的类,所以我们,通过使用function开始一个简单的例子。
现在,我们使用一个真实的类来实现元类,但是做的是同样的事情。
但是这不是真正的OOP。我们直接调用type,我们不去覆盖或者调用父类的__new__方法。
你可能已经注意到了有个额外的参数upperattr_metaclass,这并没有什么特别的。类方法的第一个参数总是表示当前的实例,就像在普通的类方法中的self参数一样。当然了,为了清晰起见,这里的名字我起的比较长。但是就像self一样,所有的参数都有它们的传统名称。因此,在真实的产品代码中一个元类应该是像这样的:
如果使用super方法的话,我们还可以使它变得更清晰一些,这会容易继承(是的,你可以拥有元类,从元类继承,从type继承)
就是这样,除此之外,关于元类真的没有别的可说的了。使用到元类的代码比较复杂,这背后的原因倒并不是因为元类本身,而是因为你通常会使用元类去做一些晦涩的事情,依赖于自省,控制继承等等。确实,用元类来搞些“黑暗魔法”是特别有用的,因而会搞出些复杂的东西来。但就元类本身而言,它们其实是很简单的:
拦截一个类的创建
学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!
一、Python所有方向的学习路线
Python所有方向路线就是把Python常用的技术点做整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
二、学习软件
工欲善其事必先利其器。学习Python常用的开发软件都在这里了,给大家节省了很多时间。
三、全套PDF电子书
书籍的好处就在于权威和体系健全,刚开始学习的时候你可以只看视频或者听某个人讲课,但等你学完之后,你觉得你掌握了,这时候建议还是得去看一下书籍,看权威技术书籍也是每个程序员必经之路。
四、入门学习视频
我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。
五、实战案例
光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
六、面试资料
我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
/img-blog.csdnimg.cn/img_convert/d2d978bb523c810abca3abe69e09bc1a.png)
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!