元类

1、什么是元类?

在python中一切皆对象,那么我们用class关键字定义的类本身也是对象;

负责产生该对象的类叫做元类,即元类也可以简称类的类

class Foo: #Foo=元类()

         pass

2、为什么要用元类?

元类是负责产生类的,所以我们学习元类或者自定义类的目的是为了控制类的产生过程,

还可以控制对象的产生过程。

3、怎么用

#储备知识内置函数exec用法
# cmd="""
# x=1
# y =2
# def func(self):
# pass
# """
# class_dic={}
# exec(cmd,{},class_dic)
# exec会执行cmd对应的字符串中的代码,将执行中产生的名字(x,y,func)丢入class_dic
# 模仿了类定义阶段造名称空间的操作
# print(class_dic)


1)创建类的方法有两种
#前提:如果说类也是对象的话,那么用class关键字去创建类的过程也是一个实例化的过程,
#该实例化的目的是为了得到一个类,调用的是元类
#方式一:用class关键字去创建,用默认的元类
# class People: #People= type(.....) 造类
# country = 'china'
# def __init__(self,name,age):
# self .name= name
# self .age= age
# def eat(self):
# print('%s in eating'%self.name)
#
# peo= People ('qqc',18)
# print(type(People )) # <class 'type'> #查看默认元类

#创造类的3个要素 :类名 基类 类的名称空间
# class_name='People'
# class_bases=(object,)
# class_dic={} #类的名称空间
# class_body="""
# country='China'
# def __init__(self,name,age):
# self.name=name
# self.age=age
# def eat(self):
# print('%s is eating' %self.name)
# """
# exec(class_body,{},class_dic)

#准备好累的三要素
# print(class_name )
# print(class_bases)
# print(class_dic)
# People = type(class_name ,class_bases ,class_dic ) #用type生成类People
# print(People )
方式二;用自定义的元类
# class Mymeta(type):  # 只有继承了type类才能称为一个元类,否则就是一个普通自定义类
# def __init__(self,class_name ,class_bases ,class_dic):
# print(self ) #现在的People身份是Mymeta实例化后的对象
# print(class_name)
# print(class_bases)
# print(class_dic)
# super (Mymeta ,self).__init__(class_name ,class_bases ,class_dic)
# 加入父类属性

#class 自定义类的运行原理(非元类运行原理)
#1、拿到字符串类名 class_name= People
#2、拿到父类class_bases=(object,...)
#3、执行类体代码,拿到类的名称空间 class_dic={} 通过exec方法
#4、调用type 将三个元素传入,完成实例化 People= type(class_name ,class_bases ,class_dic)

# class People(object,metaclass= Mymeta): #People =Mymeta(...) 用自定义类进行实例化
# country = 'china'
# def __init__(self,name,age):
# self .name= name
# self .age= age
# def eat(self):
# print('%s in eating'%self.name)
(2)自定义元类控制类的产生过程,类的产生过程其实就是元类的调用过程
class Mymeta(type):  # 只有继承了type类才能称为一个元类,否则就是一个普通自定义类
# def __init__(self,class_name ,class_bases ,class_dic):
# if class_dic .get('__doc__')is None or len(class_dic .get('__doc__').strip())==0:
# #如果文档为空或者去空格后长度为0
# raise TypeError ('类中必须要有文档注释,不能为空')
# if not class_name .istitle():
# raise TypeError ('首字母要大写')
# super (Mymeta ,self).__init__(class_name ,class_bases ,class_dic)
#
# class People(object,metaclass= Mymeta): #People =Mymeta(People,object,{) 用自定义类进行实例化
# ''' 好好 '''
# country = 'china'
# def __init__(self,name,age):
# self .name= name
# self .age= age
# def eat(self):
# print('%s in eating'%self.name)
# print(People .__dict__ )
 
(3)自定义元类控制类的调用过程,即类的实例化过程(控制类对象创建)
储备知识:__call__
# class Foo:
# def __call__(self, *args ,**kwargs ):
# print(self )
# print(args )
# print(kwargs )
# pass
# obj= Foo()
# obj(5,6,x=1)
# 要想让obj成为一个可调用对象,需要在该对象的类中定义__call__方法
例题:
class Mymeta(type):
def __call__(self, *args ,**kwargs):
print(self) #self 就是People
print(args )
print(kwargs )
return 'tt'
#1、造people 的空对象
obj= self .__new__(self)
#2、为对象初始化独有属性
print(args ,kwargs )
self.__init__(obj,*args ,**kwargs )
#3、返回一个初始化好的对象
return obj

class Foo(object,metaclass= Mymeta): #People =Mymeta(People,object,{) 用自定义类进行实例化
''' 好好 '''
country = 'china'
def __init__(self,name,age):
self .name= name
self .age= age
def eat(self):
print('%s in eating'%self.name)
h= Foo('qqc",6)

#分析:调用People的目的
#先造出People的空对象,为该对象初始化独有的属性
obj = People ('qqc',age=123)
print(obj.name )

 运行过程: Foo('qqc',6)在实例化时,触发了元类Mymatw中的__call__功能,把自己当成参数传给了self,'qqc',6传给了*args,**kwargs
#然后通过__new__方法创建了空对象obj,再通过__init__方法,类Foo给对象obj初始化属性,最后返回对象obj(h)
 





posted @ 2018-07-02 16:32  朝朝哥  阅读(152)  评论(0编辑  收藏  举报