【Python基础知识库】Python中的元类metaclass

    技术2025-11-14  26

    不会很常用,在ORM这种复杂结构中会遇到,同时在看一些框架源代码的过程中可能会遇到很多元类的实例,看起来很晦涩。推荐Stack overflow 一些专业解答,也可以参考下这篇博客的深刻理解,很详细。

    str是用来创建字符串对象的类int是用来创建整数对象的类type就是创建类对象的类

    通过type函数动态创建类

    # type的语法 type(class_name, class_parents, class_attr_dict) """ class_name: 类名 class_parents: 父类的元组(针对集成的情况,可为空) class_attr_dict: 包函属性的字典 """ eg: class MyClass(object): pass MyClass = type('MyClass', (), {'foo':True})

    元类:就是能够创建python中类这种对象的东西,如type就是Python的内建元类

    MyClass = MetaClass() # 元类的创建 my_class = MyClass() # 类的实例

    实际上Myclass就是通过type()来创建出的MyClass类,它是type()类的一个实例。 同时,MyClass本身也是累,也可以创建自己的实例my_class。

    metaclass

    可以再写一个类的时候为其添加__metaclass__属性,这样就定义了这个类的元类。__metaclass__实际上可以被任意调用,它并不需要是一个正式的类。

    # py2 class Foo(object): __metaclass__ = something # py3 class Foo(metaclass=something): __metaclass__ = something 自定义元类

    元类的主要目的为了当创建类时能够自动改变类,通常,你会为API做这样的事情,你希望可以创建符合当前上下文的类。

    可以使用函数当做元类 # 元类通常会将你传给type的参数作为自己的参数传入 def upper_attr(future_class_name, future_class_parents, future_class_attr): """返回一个类对象,将属性都转为大写形式""" # 选择所有不以'__'开头的属性 attrs = ((name, value) for name, value in future_class_attr.items() if not name.startswith('__')) # 将他们转化为大写形式 uppercase_attr = dict{(name.upper(), value) for name, value in attrs} # 通过type来做类对象的创建 return type(future_class_name, future_class_parents, uppercase_attr) # 返回一个对象,这个对象是个类 class Foo(metaclass=upper_attr): _metaclass__ = upper_attr bar = 'bip' print(hasattr(Foo, 'bar')) # False print(hasattr(Foo, 'BAR')) # True f = Foo() print(f.BAR) # 'bip' 可以使用class来当做元类 class UpperAttrMetaClass(type): def __new__(upperattr_metaclass, future_class_name, future_class_parents, future_class_attr): attrs = ((name, value) for name, value in future_class_attr.items() if not name.starswith('__')) uppercase_attr = dict((name.upper(), value) for name, value in attrs) # 复用type.__new__方法,OOP编程。 # 由于type是元类也是类,本身也是通过__new__方法生成实例,只不过这个实例是一个类。 return tpye.__new__(upperattr_metaclass, future_classs_name, future_class_parents, uppercase_attr) 真实业务场景下的元类 class UpperAttrMetaClass(type): def __new__(cls, name, bases, dct): attrs = ((name, value) for name, value in dct.items() if not name.startswith('__')) uppercase_attr = dict((name.upper(), value) for name, value in attrs) return type.__new__(cls, name, bases, uppercase_attr) # supper继承 class UpperAttrMetaClass(type): def __new__(cls, name, bases, dct): attrs = ((name, value) for name, value in dct.items() if not name.startswith('__')) uppercase_attr = dict((name.upper(), value) for name, value in attrs) return supper(UpperAttrMetaClass, cls).__new__(cls, name, bases, uppercase_attr) 使用元类创建ORM实例

    熟悉Django框架的,应该知道ORM结构,元类创建API,使得调用简洁明了。

    # -*- coding:utf-8 -*- # 1.定义Field类,用于保存数据表的字段名和字段类型 class Field(object): def __init__(self, name, column_type): self.name = name self.column_type = column_type def __str__(self): return '<%s:%s>' % (self.__class__.__name__, self.name) class StringField(Field): def __init__(self, name): super().__init__(name, 'varchar(100)') class IntegerField(Field): def __init__(self, name): super().__init__(name, 'bigint') # 定义元类,控制Model对象的创建 class ModelMetaClass(type): """定义元类""" def __new__(cls, name, bases, attrs): if name == 'Model': return type.__new__(cls, name, bases, attrs) print('Found model: %s' % name) # 排除掉对Model类的修改 mappings = dict() for k, v in attrs.items(): # 保存类属性和列的映射关系到mappings字典 if isinstance(v, Field): print('Found mapping: %s==>%s' % (k, v) mappings[k] = v for k in mappings.keys(): # 将类属性移除,是定义的类字段不污染User类属性,只在实例中可以访问这些key attrs.pop(k) # 假设表名为类名的小写,创建类时添加一个__table__类属性 attrs['__table__'] = name.lower() # 保存属性和列的映射关系,创建类时添加一个__mappings__类属性 attrs['__mappings__'] = mappings return type.__new__(cls, name, bases, attrs) # 编写Model基类 class Model(dict, metaclass= ModelMetaClass): """只是简单实现了INSERT功能""" def __init__(self, **kw): super(Model, self).__init__(**kw) def __getattr__(self, key): try: return self[key] except KeyError: raise AttributeError(r"'Model' object has no attribute '%s'" % key) def __setattr__(self, key, value): self[key] = value def save(self): fields = [] params = [] args = [] for k, v in self.__mappings__.items(): fields.append(v.name) params.append('?') args.append(getattr(self, k, None)) sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(params)) print('SQL: %s' % sql) print('ARGS: %s' % str(args)) # 创建一个model,用户表User,定义数据字段就可实现数据表和字段的操作 class User(Model)id = IntegerField('id') # 对应数据表的id字段 name = StringField('username') # 对应数据表的username字段 email = StringField('email') # 对应数据表的email字段 password = StringField('password') # 对应数据表的password字段 # 创建一个实例 user = User(id=123456, name='Michael', email='test@163.com', password='123456') # 保存数据库 user.save()
    Processed: 0.016, SQL: 9