python type与__metaclass__的使用

本文深入探讨了Python元类的应用,通过实例展示了如何使用元类实现自定义列表的add方法及ORM框架的save方法,为读者提供了理解元类及其实现细节的途径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 通过__metaclass__实现自定义列表add方法:

 1 class ListMetaclass(type):
 2     """
 3     通过__metaclass__动态生成类,为新生成的类添加add方法
 4     """
 5 
 6     def __new__(cls, *args, **kwargs):
 7         """
 8         :param args: args包含了三个参数具体如下:
 9             args[0]: 调用ListMetaclass的类名,这边为"MyList"
10             args[1]: 为MyList所继承的父类,这边为"(<type 'list'>,)"
11             args[2]: 为MyList类所包含的属性与方法, {'__module__': '__main__', '__metaclass__': <class '__main__.ListMetaclass'>}
12         :param kwargs:
13         :return: 返回后必须将这三个参数全部返回
14         """
15         args[2]["add"] = lambda List, value: List.append(value)
16         return type.__new__(cls, *args)
17 
18 class MyList(list):
19     __metaclass__ = ListMetaclass
20 
21 c = MyList()
22 c.add(10)
23 print c
View Code

打印结果如下:

 2. 通过__metaclass__实现ORM的save方法:

  1 class Field(object):
  2     def __init__(self, name, column_type):
  3         self.name = name
  4         self.column_type = column_type
  5 
  6     def __str__(self):
  7         return '<%s:%s>' % (self.__class__.__name__, self.name)
  8 
  9 class StringField(Field):
 10     def __init__(self, name):
 11         super(StringField, self).__init__(name, 'varchar(100)')
 12 
 13 class IntegerField(Field):
 14     def __init__(self, name):
 15         super(IntegerField, self).__init__(name, 'bigint')
 16 
 17 class ModelMetaclass(type):
 18 
 19     def __new__(cls, name, bases, attrs):
 20         """
 21         :param name:
 22         :param bases:
 23         :param attrs:  这边attrs为User类中的数据属性,也就是每个变量对应一个文件类型的对象,具体如下:
 24             {
 25                 'email': <__main__.StringField object at 0x0000000002827550>,
 26                 '__module__': '__main__',
 27                 'password': <__main__.StringField object at 0x0000000002827588>,
 28                 'id': <__main__.IntegerField object at 0x00000000028274E0>,
 29                 'name': <__main__.StringField object at 0x0000000002827518>
 30             }
 31         :param 在逻辑处理完成后, __mappings__数据为:
 32             {
 33                 'password': <__main__.StringField object at 0x00000000028C75F8>,
 34                 'email': <__main__.StringField object at 0x00000000028C75C0>,
 35                 'name': <__main__.StringField object at 0x00000000028C7588>,
 36                 'id': <__main__.IntegerField object at 0x00000000028C7550>
 37             }
 38         :return:
 39         这边的__metaclass__主要就是实现了对User类中文件对象的数据进行筛选,因为只有文件对象的数据才需要来拼接sql语句
 40         """
 41         if name =='Model':
 42             return type.__new__(cls, name, bases, attrs)
 43         print('Found model: %s' % name)
 44         mappings = dict()
 45         for k, v in attrs.iteritems():
 46             #判断attrs中key对应的value是否为文件对象, 如果是则将对象赋值到mappings字典中
 47             if isinstance(v, Field):
 48                 print('Found mapping: %s ==> %s' % (k, v))
 49                 mappings[k] = v
 50 
 51         # 先删除attr原先中文件对象,然后添加__mappings__方法,Model类中的save可以通过__mappings__中存放的文件对象来
 52         # 实现数据的获取
 53         for k in mappings.iterkeys():
 54             attrs.pop(k)
 55         attrs['__mappings__'] = mappings # 保存属性和列的映射关系
 56         attrs['__table__'] = name # 假设表名和类名一致
 57         return type.__new__(cls, name, bases, attrs)
 58 
 59 
 60 class Model(dict):
 61     __metaclass__ = ModelMetaclass
 62 
 63     def __init__(self, **kw):
 64         super(Model, self).__init__(**kw)
 65 
 66     def __getattr__(self, key):
 67         try:
 68             return self[key]
 69         except KeyError:
 70             raise AttributeError(r"'Model' object has no attribute '%s'" % key)
 71 
 72     # def __setattr__(self, key, value):
 73     #     self[key] = value
 74 
 75     def save(self):
 76         fields = []
 77         params = []
 78         for k, v in self.__mappings__.iteritems():
 79             fields.append(v.name)
 80             params.append(str(getattr(self, k, None)))
 81         args = " ("
 82         for i in params:
 83             args += "'{}',".format(i)
 84         sql = 'insert into %s (%s) values' % (self.__table__, ','.join(fields)) + args + ")"
 85         print('SQL: %s' % sql)
 86 
 87 class BoolObj(object):
 88     pass
 89 
 90 
 91 class User(Model):
 92     id = IntegerField('uid')
 93     name = StringField('username')
 94     email = StringField('email')
 95     password = StringField('password')
 96 
 97 #这边User()实列化,由于User类继承了dict类,实际上就相当于dict(id=12345, name='Michael', email='test@orm.org', password='my-pwd')
 98 #所有此时打印出来的u就是字典显示 {'email': 'test@orm.org', 'password': 'my-pwd', 'id': 12345, 'name': 'Michael'}
 99 u = User(id=12345, name='Michael', email='test@orm.org', password='my-pwd')
100 u.save()
View Code

打印结果如下:

 

转载于:https://www.cnblogs.com/grub007/p/9924009.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值