深入理解Python的元类_python 类里 factory class

本文解释了在Python中如何动态创建类,使用`type`函数和元类的概念。元类是创建类的工人,允许在类创建时进行自定义。文章介绍了`__metaclass__`的作用,以及如何使用自定义元类实现特定的类创建规则,如转换属性大小写。
摘要由CSDN通过智能技术生成

例如:

可以手动的这样创建:

你注意到我们使用’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行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值