面向对象(六)——元类

元类

一、什么是元类

1、在python中,一切皆对象,而对象都是由类实例化得到的。对象是调用类或自定义类得到的,如果说一切皆对象,那么自定义类也是一个对象,只要是对象都是调用一个类实例化得到

2、对象tea1是调用类OldboyTeacher产生的,而OldboyTeacher类也是通过调用一个类实例化对象获得,即OldboyTeacher = 元类(……)内置的元类是type

  (1)调用元类------->自定义的类

  (2)调用自定义的类-------->自定义的对象  

class OldboyTeacher:
    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex
    def score(self):
        print('%s is scoring' %self.name)

tea1=OldboyTeacher('egon',18,'male')
print(type(OldboyTeacher))     # type

二、class关键字创建类的底层原理

1、先拿到类名      

2、再拿到类的基类

3、然后拿到类的名称空间 (执行类体代码,将产生的名字放到类的名称空间也就是一个字典里)

4、调用type元类实例化得到自定义的类

 1 #1.拿到类名
 2 class_name = 'OldboyTeacher'
 3 
 4 #2.拿到类的父类
 5 class_bases = (object)
 6 
 7 #3.拿到类的名称空间
 8 class_dict={}
 9 class_body='''
10 school = 'Oldboy'
11 
12 def __init__(self,name,age,sex):
13     self.name=name
14     self.age=age
15     self.sex=sex
16 
17 def score(self):
18     print('%s is scoring' %self.name)
19 '''
20 exec(class_body,{},class_dict)
21 
22 #4.调用元类type产生自定义的类
23 OldboyTeacher=type(class_name,class_bases,class_dict)
24 
25 print(OldboyTeacher)   # type
不依赖class关键字创建一个自定义类

三、自定义元类来控制类的产生

1、模板

 1  class Mymeta(type): #但凡继承了type的类才能称之为自定义的元类,否则就是只是一个普通的类
 2      def __init__(self,class_name,class_bases,class_dic):
 3          print(self)
 4          print(class_name)
 5          print(class_bases)
 6          print(class_dic)
 7 
 8 class OldboyTeacher(object,metaclass=Mymeta): # OldboyTeacher=Mymeta('OldboyTeacher',(object,),{...})
 9      school = 'Oldboy'
10 
11      def __init__(self,name,age,sex):
12          self.name=name
13          self.age=age
14          self.sex=sex
15 
16      def score(self):
17          print('%s is scoring' %self.name)
模板

2、控制类的产生

(1)类名必须要驼峰体

(2)类体必须有文档注释,且文档注释不能为空

 1 class Mymeta(type): #但凡继承了type的类才能称之为自定义的元类,否则就是只是一个普通的类
 2     def __init__(self,class_name,class_bases,class_dic):
 3         if class_name.islower():
 4             raise TypeError('类名必须使用驼峰体')
 5 
 6         doc=class_dic.get('__doc__')
 7         if doc is None or len(doc) == 0 or len(doc.strip('\n ')) == 0:
 8             raise TypeError('类体中必须有文档注释,且文档注释不能为空')
 9 
10 class OldboyTeacher(object,metaclass=Mymeta): #OldboyTeacher=Mymeta('OldboyTeacher',(object,),{...})
11     school = 'Oldboy'
12 
13     def __init__(self,name,age,sex):
14         self.name=name
15         self.age=age
16         self.sex=sex
17 
18     def score(self):
19         print('%s is scoring' %self.name)
20 
21 
22 print(OldboyTeacher.__dict__)
View Code

四、自定义元类来控制类的调用

1、自定义元类

凡继承了type的类才能称之为自定义的元类,否则就是只是一个普通的类

2、实例化类

(1)先产生一个空对象
(2)执行__init__方法,完成对象的初始属性操作
(3)返回初始化好的那个对象

3、对象之所以可以调用,是因为对象的类中有方法__call__。所以,自定义类作为对象时,定义它的类中有__call__方法,就可以调用

4、调用自定义类

调用OldboyTeacher(...)就是在调用OldboyTeacher的类中的__call__,那么在该__call__中就需要做上述三件事

 1 class Mymeta(type): #但凡继承了type的类才能称之为自定义的元类,否则就是只是一个普通的类
 2     def __call__(self, *args, **kwargs): #self=OldboyTeacher这个类,args=('egon',18,'male'),kwargs={}
 3         # 1. 先产生一个空对象
 4         tea_obj=self.__new__(self) #tea_obj是OldboyTeacher这个类的对象
 5         # 2. 执行__init__方法,完成对象的初始属性操作
 6         self.__init__(tea_obj,*args,**kwargs)
 7         # 3. 返回初始化好的那个对象
 8         return tea_obj
 9 
10 class OldboyTeacher(object,metaclass=Mymeta): #OldboyTeacher=Mymeta('OldboyTeacher',(object,),{...})
11     school = 'Oldboy'
12 
13     #            tea_obj,'egon',18,'male'
14     def __init__(self,name,age,sex):
15         self.name=name
16         self.age=age
17         self.sex=sex
18 
19     def score(self):
20         print('%s is scoring' %self.name)
21 
22 tea1=OldboyTeacher('egon',18,'male') # 会触发OldboyTeacher的类(即元类)中的__call__函数
23 print(tea1)
24 print(tea1.__dict__)
自定义元类控制类的调用
 1 class Mymeta(type): #但凡继承了type的类才能称之为自定义的元类,否则就是只是一个普通的类
 2     def __call__(self, *args, **kwargs): #self=OldboyTeacher这个类,args=('egon',18,'male'),kwargs={}
 3         # 1. 先产生一个空对象
 4         tea_obj=self.__new__(self) #tea_obj是OldboyTeacher这个类的对象
 5         # 2. 执行__init__方法,完成对象的初始属性操作
 6         self.__init__(tea_obj,*args,**kwargs)
 7         # print(tea_obj.__dict__)
 8         tea_obj.__dict__={('_%s__%s' %(self.__name__,k)):v for k,v in tea_obj.__dict__.items()}
 9         # 3. 返回初始化好的那个对象
10         return tea_obj
11 
12 class OldboyTeacher(object,metaclass=Mymeta): #OldboyTeacher=Mymeta('OldboyTeacher',(object,),{...})
13     school = 'Oldboy'
14 
15     def __init__(self,name,age,sex):
16         self.name=name
17         self.age=age
18         self.sex=sex
19 
20     def score(self):
21         print('%s is scoring' %self.name)
22 
23 tea1=OldboyTeacher('egon',18,'male') # 会触发OldboyTeacher的类(即元类)中的__call__函数
24 # print(tea1)
25 print(tea1.__dict__)
将自定义类中的的变量都修改为私有变量

猜你喜欢

转载自www.cnblogs.com/linagcheng/p/9542858.html