美文网首页
Python:15.元类

Python:15.元类

作者: 许瘦子来世 | 来源:发表于2018-07-12 10:23 被阅读37次
    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    'a test module'
    
    __author__ = 'Alex Xu'
    
    # 元类
    '''
    1. 元类:metaclass。
    2. 先定义metaclass,就可以创建类,最后创建实例
    '''
    
    # ORM(Object Relational Mapping)对象-关系映射
    # 定义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)
    
    # 基于Field派生
    class StringField(Field):
        def __init__(self, name):
            super(StringField, self).__init__(name, 'varchar(100)')
    
    class IntegerField(Field):
        def __init__(self, name):
            super(IntegerField, self).__init__(name, 'bigint')
    
    # 编写ModelMetaclass
    '''
    1. 排除掉对Model类的修改
    2. 在当前类中查找定义的类的所有属性,
    如果找到一个Field属性,就把它保存到一个__mappings__的dict中,
    同时从类属性中删除该属性,否则容易造成运行时错误(实例属性会遮盖类的同名属性)
    3. 把表名保存到__table__中,这里简化为表名默认为类名
    '''
    class ModelMetaclass(type):
        def __new__(cls, name, bases, attrs):
            if name == 'Model':
                return type.__new__(cls, name, bases, attrs)
            print('Found model: %s' % name)
            mappings = dict()
            for k,v in attrs.items():
                if isinstance(v, Field):
                    print('Found mapping: %s ==> %s' % (k,v))
                    mappings[k] = v
            for k in mappings.keys():
                attrs.pop(k)
            attrs['__mappings__'] = mappings # 保存属性和列的映射关系
            attrs['__table__'] = name # 假设表名和类名一致
            return type.__new__(cls, name, bases, attrs)
    
    # 基类model
    class Model(dict, metaclass=ModelMetaclass):
        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))
    
    # 调用
    class User(Model):
        # 定义类的属性到列的映射
        id = IntegerField('id')
        name = StringField('username')
        email = StringField('email')
        password = StringField('password')
    
    u = User(id = 12345, name = 'Michael', email = 'test@gmail.com', password = 'my-pwd')
    u.save()
    

    相关文章

      网友评论

          本文标题:Python:15.元类

          本文链接:https://www.haomeiwen.com/subject/leylpftx.html