什么是元类

元类是类的类,是类的模板,用来控制如何创建类的,正如类是创建对象的模板一样,typepython的一个内建元类,用来直接控制生成类,python中任何class 定义的类其实是type 类实例化的对象

class MyClass(object):
    pass

'''type就是所有类默认的元类'''

obj = MyClass()
print(type(obj))
# <class '__main__.MyClass'>

print(type(MyClass))
# <class 'type'>

如何产生类

  1. 利用class 关键字
# class 类名

class MyClass(object):
    pass


print(MyClass)
# <class '__main__.MyClass'>
  1. type元类
# type(类名, 父类, 类的名称空间)

res = type('MyClass', (), {})
print(res)
# <class '__main__.MyClass'>

基本使用

class MyTypeClass(type):
    def __init__(cls, cls_name, cls_bases, cls_dict):  # cls用来接收类
        if not cls_name.istitle():
            raise Exception("类名的首字母必须大写")
        super.__init__(cls_name, cls_bases, cls_dict)
        # print(cls, cls_name, cls_bases, cls_dict)
        # <class '__main__.MyClass'> MyClass () {'__module__': '__main__', '__qualname__': 'MyClass', 'student': 'kevin'}


# 元类是不能通过继承的方式直接指定的,需要关键字metaclass
class MyClass(metaclass=MyTypeClass):
    student = 'kevin'


print(type(MyClass))
# <class '__main__.MyTypeClass'>


class a(metaclass=MyTypeClass):
    pass
# Exception: 类名的首字母必须大写

进阶操作

对象加括号会自动执行产生该对象的类里面的__call__。类加括号会执行元类的里面的__call__

对象的产生过程:先执行元类里面的__call__,然后调用类里面的双下__init__

class MyTypeClass(type):
    def __call__(self, *args, **kwargs):
        print('执行__call__')
        super().__call__(*args, **kwargs)


class MyClass(metaclass=MyTypeClass):
    def __init__(self, name):
        print('执行__init__')
        self.name = name


obj = MyClass('kevin')
# 执行__call__
# 执行__init__
class MyTypeClass(type):
    def __call__(self, *args, **kwargs):
        # print('__call__ run')
        # print(args,kwargs)
        # 规定:类在实例化产生对象的时候 对象的独有数据必须采用关键字参数
        if args:
            raise Exception('必须全部采用关键字参数')
        super().__call__(*args, **kwargs)


class MyClass(metaclass=MyTypeClass):
    def __init__(self, name):
        # print('__init__ run')
        self.name = name
        
obj = MyClass(name='kevin')

笔试题

编写元类规定对象的所有数据值转大写
Eg:

 `obj.name = 'kevin'`
 `print(obj.name)  # KEVIN`
class MyTypeClass(type):
    def __call__(self, *args, **kwargs):
        args = [i.upper() for i in args]
        return super().__call__(*args, **kwargs)


class MyClass(metaclass=MyTypeClass):
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender

    def __setattr__(self, key, value):
        self.__dict__[key] = value.upper()


obj = MyClass('kevin', 'male')

print(obj.name)
# KEVIN
obj.hobby = 'run'
print(obj.hobby)
# RUN
Last modification:April 15, 2022
如果觉得我的文章对你有用,请随意赞赏