Python中的元类有什么作用,用法是怎样的
Admin 2022-08-17 群英技术资讯 320 次浏览
python语言因为工作偏向于 AI ,所以对于这门语言还停留在表面,对于 python 深层并没有接触到。
今天来聊一聊元类(metaclass) ,想必大多数人都或多或少听过元编程这个词,但是对于元编程是什么以及如何应用元编程熟悉应该不多,在 python 中的 metaclass 就是帮助 developer 实现元编程,因此产生一个想法
最近时间还算宽裕,所以想要文章认真弄一弄
在 python 语言中,并没有函数重载,我们下面通过一个具体例子来说明。
class A(): def f(self, x:int): print('A.f int overload',self,x) def f(self,x:str): print('A.f str overload',self,x) def f(self,x,y): print('A.f two arg overload',self,x,y) if __name__ == "__main__": a = A() a.f(1)
当执行上面代码我们会得到一个错误信息,实例化 A 类后,调用实例的 f 方法,因为在 python 语言中没有重装方法,所以 def f(self,x:str)
会覆盖之前的 def f(self, x:int)
, 而 def f(self,x,y)
方法会覆盖于 def f(self,x:str)
方法,所以当通过传入 1 一个参数,不会调用 def f(self,x:int)
而是调用 def f(self,x,y)
方法。
TypeError: f() missing 1 required positional argument: 'y'
那么什么是正确的姿势解决这个问题呢? 这里先不急于给出答案,当我们介绍完 metaclass 后,答案就自然浮出水面。
想要了解 Metaclass 也就是元类,meta 在英文中超越的意思,也就是 Metaclass 是高级于 class,用于创建 class 的 class。有的时候我们需要控制类创建过程,通常创建类工作是由 type 完成的,因为 type 直接设计到 c,我们希望在 type 创建类过程插入一些自定义的东西,所以引入了 Metaclass 让某一个类创建工作不再由 type 来实现,而是由指定 class 来实现
在 python 中,我们可以通过 class 来实例化对象,不过这里要说在 python 中 class 其实也是对象。既然 class 也是对象,那么 class 的类型又是什么呢
class A: a = 1 b = "hello" def f(self): return 12 def main(): print(f'{type(2)=}') print(f'{type("hello")=}') print(f'{type([])=}') print(f'{type(A())=}') if __name__ == "__main__": main()
输出一下 2、hello 、空数组和 A 类实例的类型,结果发现他们类别分别为 int、str、list 和 A 类别。其实他们也是对象,既然是对象,那么就会有一个 class 用于创建这个类别。
type(2)=<class 'int'> type("hello")=<class 'str'> type([])=<class 'list'> type(A())=<class '__main__.A'>
接下来我们就看一下这些 class(int,str,list) 那么这些对象又是什么类别呢
class A: a = 1 b = "hello" def f(self): return 12 if __name__ == "__main__": print(f'{type(int)=}') print(f'{type(str)=}') print(f'{type(list)=}') print(f'{type(A)=}')
type(int)=<class 'type'> type(str)=<class 'type'> type(list)=<class 'type'> type(A)=<class 'type'>
不难看出多有 class 的类型都是 type ,例如数字 2 的 int 的一个实例,而 int 又是 type 的一个实例。
如果大家从类似 java 这些语言开始,然后再去学习 python 可能会有这样疑问,在 python 中 type 和 class 有什么区别,他们不都是类型吗? 其实答案就是这两者在 python3 中并没有区别,可以将他们看做一个东西。
def main(): x = int() print(f'{x=}') B = type('B',(),{}) print(f'{B=}') if __name__ == "__main__": main()
不过如果进一步深入研究,两种 class 和 type 在字面上,是不同两样东西,class 作为关键字来定义类型时,是调用其构造器来做了一些初始化的工作。
def main(): x = int() print(f'{x=}') B = type('B',(),{}) print(f'{B=}') if __name__ == "__main__": main()
我们可以这样来定义一个类型
x=0 B=<class '__main__.B'>
可以用 class 方式来定义一个类 A,然后我们在用 type 方式来创建一个类,type 接受 3 个参数分别是类的名称,这里接受的字符串类型的名称、以及该类的基类,是组元的形式,接下来是就是一个属性,属性是字典形式数据,键是属性名称,值是属性值。
class A: a = 2 b = 'hello' def f(self): return 12
下面我们用 make_A
来创建一个类, 这里使用 type 来定义一个类
def make_A(): name = 'A' bases = () a = 2 b = 'hello' def f(self): return 12 namespace = {'a':a,'b':b,'f':f} A = type(name,bases,namespace) return
通过 type 创建类时候需要传入类名称 A 然后 base 是一个要创建类 A 的基类,namescpace 是类属性,是 dict 形式,键是属性名称,而值是属性值。
def make_A_more_accurate(): name = 'A' bases = () namespace = type.__prepare__(name,bases) body = ( """ a = 1 b = 'hello' def f(self): return 12 """ ) exec(body,globals(),namespace) A = type(name,bases,namespace) return A
metaclass 是继承于 type,那么 metaclass 的工作也是用于创建 class,我们可以在 metaclass 中做一些自定义的事情,
这里可能比较难理解是 __prepare__
上网找到关于 __prepare__
解释,暂时说一下自己认识,可能有点浅,感觉就是为类创建了一个局部的作用域。
namespace = type.__prepare__(name,bases) print(namespace)
type.__prepare__
应该是返回一个局部命名空间,
exec(body,globals(),namespace)
class Tut: ... tut = Tut() print(f'{type(tut)=}') print(f'{type(Tut)=}')
上面例子定义一个类,然后实例化 Tut 类得到对象 tut,接下来分别输出 tut 和 Tut 类型
type(tut)=<class '__main__.Tut'> type(Tut)=<class 'type'>
不难看出 tut 是 Tut 的实例,而 Tut 是 type 的对象
class TutMetaClass(type): ... class Tut(metaclass=TutMetaClass): ...
然后我们定义一个 TutMetaClass 继承于 type,然后将 Tut 类的 metaclass 指向 TutMetaClass ,然后 tut 类型为 Tut,而 Tut 类型为 TutMetaClass 类型
type(tut)=<class '__main__.Tut'> type(Tut)=<class '__main__.TutMetaClass'>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
Kivy 是用 Python 和 Cython 编写的,基于 OpenGL ES 2,支持各种输入设备并拥有丰富的部件库。本文将教你如何使用 Kivy 编写一款乒乓球游戏,感兴趣的可以动手试一试
PyQt提供了一个设计良好的窗口控件集合,具有更方便的操作性。学过VB的同学会知道,相比与VB的使用,在界面设计上元素更丰富,这篇文章主要介绍了基于PyQt5完成的图转文功能,需要的朋友可以参考下
本文详细讲解了Pytest框架之fixture,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
python脚本执行的3种方法:方法一:交互模式直接执行语句方法二:通过脚本输出方法三:脚本中指定 python 路径,修改文件为可执行文件
这篇文章主要介绍了如何用 Python 子进程关闭 Excel 自动化中的弹窗,帮助大家更好的理解和学习使用python,感兴趣的朋友可以了解下
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008