浮躁是人生最大的敌人

面向对象——元类

Posted on 2019-04-29 08:20  King'home  阅读(368)  评论(0编辑  收藏  举报

1、什么是元类

元类:产生类的类

# 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(tea1))
# print(type(OldboyTeacher))

对象tea1是调用OldboyTeacher类得到的,如果说一切皆对象,那么OldboyTeacher也是一个对象,只要是对象
都是调用一个类实例化得到的,即OldboyTeacher=元类(...),内置的元类是type

2、关系:

①调用元类————》自定义的类
②调用自定义的类————》自定义的对象

3、不依赖class关键字创建一个自定义的类
①拿到类名

class_name='OlaboyTeacher'

②拿到类的基类们

calssbases=(object,)


③拿到类的名称空间

class = {}
class_body = """
school = 'Oldboy'
def __init__(self ,name,age,sex)
	self.name = name
	self.age = age
	self.sex = sex
"""
exec(class_body,{},class_dic)
print(class_dic)

④调用type得到自定义的OldboyTeacher=type(‘OldboyTeacher’,(object,),{…})惊讶

OldboyTeacher=type(class_name,class_bases,class_dic)
print(OldboyTeacher)
tea1=OldboyTeache('egon',18,'male')
print(tea1.__dicet__)

自定义的类的三个组关键组成部分:
1、类名

2、类的基类们

3、类的名称空间

模板

# class Mymeta(type): #但凡继承了type的类才能称之为自定义的元类,否则就是只是一个普通的类
#     def __init__(self,class_name,class_bases,class_dic):
#         print(self)
#         print(class_name)
#         print(class_bases)
#         print(class_dic)
#
# class OldboyTeacher(object,metaclass=Mymeta): #OldboyTeacher=Mymeta('OldboyTeacher',(object,),{...})
#     school = 'Oldboy'
#
#     def __init__(self,name,age,sex):
#         self.name=name
#         self.age=age
#         self.sex=sex
#
#     def score(self):
#         print('%s is scoring' %self.name)

按类的产生:

1、类名必须用驼峰体
2、类体必须有文档注释

class Mymeta(type): #但凡继承了type的类才能称之为自定义的元类,否则就是只是一个普通的类
    def __init__(self,class_name,class_bases,class_dic):
        if class_name.islower():
            raise TypeError('类名必须使用驼峰体')

        doc=class_dic.get('__doc__')
        if doc is None or len(doc) == 0 or len(doc.strip('\n ')) == 0:
            raise TypeError('类体中必须有文档注释,且文档注释不能为空')

class OldboyTeacher(object,metaclass=Mymeta): #OldboyTeacher=Mymeta('OldboyTeacher',(object,),{...})
    school = 'Oldboy'

    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex

    def score(self):
        print('%s is scoring' %self.name)


print(OldboyTeacher.__dict__)

#自定义元类来控制类的调用(即类的实例化过程)

class Mymeta(type): #但凡继承了type的类才能称之为自定义的元类,否则就是只是一个普通的类
    def __call__(self, *args, **kwargs): #self=OldboyTeacher这个类,args=('egon',18,'male'),kwargs={}
        # 1. 先产生一个空对象
        tea_obj=self.__new__(self) #tea_obj是OldboyTeacher这个类的对象
        # 2. 执行__init__方法,完成对象的初始属性操作
        self.__init__(tea_obj,*args,**kwargs)
        # print(tea_obj.__dict__)
        tea_obj.__dict__={('_%s__%s' %(self.__name__,k)):v for k,v in tea_obj.__dict__.items()}
        # 3. 返回初始化好的那个对象
        return tea_obj

class OldboyTeacher(object,metaclass=Mymeta): #OldboyTeacher=Mymeta('OldboyTeacher',(object,),{...})
    school = 'Oldboy'

    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') # 会触发OldboyTeacher的类(即元类)中的__call__函数
# print(tea1)
print(tea1.__dict__)

# 实例化OldboyTeacher,或者说调用OldboyTeacher会
# 1. 先产生一个空对象
# 2. 执行__init__方法,完成对象的初始属性操作
# 3. 返回初始化好的那个对象
# 推导:调用OldboyTeacher(...)就是在调用OldboyTeacher的类中的__call__,那么在该__call__中就需要做上述三件事

Copyright © 2024 King'home
Powered by .NET 8.0 on Kubernetes