分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 网页技术

元类metaclass

发布时间:2023-09-06 01:37责任编辑:董明明关键词:classmeta

一 知识储备

exec:三个参数参数一:字符串形式的命令参数二:全局作用域(字典形式),如果不指定,默认为globals()参数三:局部作用域(字典形式),如果不指定,默认为locals()
exec的使用

二 引子(类也是对象)

class Foo: ???passf1=Foo() #f1是通过Foo类实例化的对象

python中一切皆是对象,类本身也是一个对象,当使用关键字class的时候,python解释器在加载class的时候就会创建一个对象(这里的对象指的是类而非类的实例),因而我们可以将类当作一个对象去使用,同样满足第一类对象的概念,可以:

  • 把类赋值给一个变量

  • 把类作为函数参数进行传递

  • 把类作为函数的返回值

  • 在运行时动态地创建类 

上例可以看出f1是由Foo这个类产生的对象,而Foo本身也是对象,那它又是由哪个类产生的呢?

1 #type函数可以查看类型,也可以用来查看对象的类,二者是一样的2 print(type(f1)) # 输出:<class ‘__main__.Foo‘> ????表示,obj 对象由Foo类创建3 print(type(Foo)) # 输出:<type ‘type‘> ?

三 什么是元类?

元类是类的类,是类的模板

元类是用来控制如何创建类的,正如类是创建对象的模板一样,而元类的主要目的是为了控制类的创建行为

元类的实例化的结果为我们用class定义的类,正如类的实例为对象(f1对象是Foo类的一个实例Foo类是 type 类的一个实例)

type是python的一个内建元类,用来直接控制生成类,python中任何class定义的类其实都是type类实例化的对象

四 创建类的两种方式

方式一:使用class关键字

class Chinese(object): ???country=‘China‘ ???def __init__(self,name,age): ???????self.name=name ???????self.age=age ???def talk(self): ???????print(‘%s is talking‘ %self.name)

 

方式二:就是手动模拟class创建类的过程):将创建类的步骤拆分开,手动去创建

#准备工作:#创建类主要分为三部分  1 类名  2 类的父类  3 类体#类名class_name=‘Chinese‘#类的父类class_bases=(object,)#类体class_body="""country=‘China‘def __init__(self,name,age): ???self.name=name ???self.age=agedef talk(self): ???print(‘%s is talking‘ %self.name)"""

步骤一(先处理类体->名称空间):类体定义的名字都会存放于类的名称空间中(一个局部的名称空间),我们可以事先定义一个空字典,然后用exec去执行类体的代码(exec产生名称空间的过程与真正的class过程类似,只是后者会将__开头的属性变形),生成类的局部名称空间,即填充字典

class_dic={}exec(class_body,globals(),class_dic)print(class_dic)#{‘country‘: ‘China‘, ‘talk‘: <function talk at 0x101a560c8>, ‘__init__‘: <function __init__ at 0x101a56668>}

步骤二:调用元类type(也可以自定义)来产生类Chinense

Foo=type(class_name,class_bases,class_dic) #实例化type得到对象Foo,即我们用class定义的类Fooprint(Foo)print(type(Foo))print(isinstance(Foo,type))‘‘‘<class ‘__main__.Chinese‘><class ‘type‘>True‘‘‘

我们看到,type 接收三个参数:

  • 第 1 个参数是字符串 ‘Foo’,表示类名

  • 第 2 个参数是元组 (object, ),表示所有的父类

  • 第 3 个参数是字典,这里是一个空字典,表示没有定义属性和方法

补充:若Foo类有继承,即class Foo(Bar):.... 则等同于type(‘Foo‘,(Bar,),{})

五 自定义元类控制类的行为

#一个类没有声明自己的元类,默认他的元类就是type,除了使用元类type,用户也可以通过继承type来自定义元类(顺便我们也可以瞅一瞅元类如何控制类的行为,工作流程是什么)
峰哥5步带你学会元类

六 练习题

练习一:在元类中控制把自定义类的数据属性都变成大写

class Mymetaclass(type): ???def __new__(cls,name,bases,attrs): ???????update_attrs={} ???????for k,v in attrs.items(): ???????????if not callable(v) and not k.startswith(‘__‘): ???????????????update_attrs[k.upper()]=v ???????????else: ???????????????update_attrs[k]=v ???????return type.__new__(cls,name,bases,update_attrs)class Chinese(metaclass=Mymetaclass): ???country=‘China‘ ???tag=‘Legend of the Dragon‘ #龙的传人 ???def walk(self): ???????print(‘%s is walking‘ %self.name)print(Chinese.__dict__)‘‘‘{‘__module__‘: ‘__main__‘, ‘COUNTRY‘: ‘China‘, ?‘TAG‘: ‘Legend of the Dragon‘, ‘walk‘: <function Chinese.walk at 0x0000000001E7B950>, ‘__dict__‘: <attribute ‘__dict__‘ of ‘Chinese‘ objects>, ?????????????????????????????????????????‘__weakref__‘: <attribute ‘__weakref__‘ of ‘Chinese‘ objects>, ‘__doc__‘: None}‘‘‘
View Code

练习二:在元类中控制自定义的类无需__init__方法

  1.元类帮其完成创建对象,以及初始化操作;

  2.要求实例化时传参必须为关键字形式,否则抛出异常TypeError: must use keyword argument

  3.key作为用户自定义类产生对象的属性,且所有属性变成大写

class Mymetaclass(type): ???# def __new__(cls,name,bases,attrs): ???# ????update_attrs={} ???# ????for k,v in attrs.items(): ???# ????????if not callable(v) and not k.startswith(‘__‘): ???# ????????????update_attrs[k.upper()]=v ???# ????????else: ???# ????????????update_attrs[k]=v ???# ????return type.__new__(cls,name,bases,update_attrs) ???def __call__(self, *args, **kwargs): ???????if args: ???????????raise TypeError(‘must use keyword argument for key function‘) ???????obj = object.__new__(self) #创建对象,self为类Foo ???????for k,v in kwargs.items(): ???????????obj.__dict__[k.upper()]=v ???????return objclass Chinese(metaclass=Mymetaclass): ???country=‘China‘ ???tag=‘Legend of the Dragon‘ #龙的传人 ???def walk(self): ???????print(‘%s is walking‘ %self.name)p=Chinese(name=‘egon‘,age=18,sex=‘male‘)print(p.__dict__)
View Code

  

元类metaclass

原文地址:https://www.cnblogs.com/llhtjwq/p/8306552.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved