前言
又是一个忘了写完的。。。。
marshmallow 是一个 ORM/ODM/框架无关的库,用于将复杂的数据类型,例如对象与Python原生数据类型之间转换的库。简单而言,就是对象序列化和反序列化,实现object -> dict
, object -> list
, string -> dict
, string -> list
的转换。(注:这篇文章将以 0.1.0 版本代码分析,可能与当前官方文档的例子有些不同)
官网示例
from datetime import date
from marshmallow import Schema, fields, pprint
class ArtistSchema(Schema):
name = fields.Str()
class AlbumSchema(Schema):
title = fields.Str()
release_date = fields.Date()
artist = fields.Nested(ArtistSchema())
bowie = dict(name='David Bowie')
album = dict(artist=bowie, title='Hunky Dory', release_date=date(1971, 12, 17))
schema = AlbumSchema()
result = schema.dump(album)
pprint(result, indent=2)
# { 'artist': {'name': 'David Bowie'},
# 'release_date': '1971-12-17',
# 'title': 'Hunky Dory'}
源码开篇
先看看 0.1.0 版本的源码结构,如下所示
marshmallow
├── __init__.py
├── base.py
├── compat.py
├── core.py # 核心代码,使用Python元类定义了Serializer,继承于BaseSerializer、SerializerMeta
├── exceptions.py
├── fields.py
├── types.py
core.py
先从 core.py 文件开始看起,该文件中主要包括了以下几个类,并应用了元类编程的思想:
class SerializerMeta(type):
def __new__(cls, name, bases, attrs):
attrs['_base_fields'] = _get_declared_fields(bases, attrs)
return super(SerializerMeta, cls).__new__(cls, name, bases, attrs)
class BaseSerializer(object):
def __init__(self, data=None):
self._data = data
self.fields = self.__get_fields() # Dict of fields
def __get_fields(self):
""""""
@property
def data(self):
""""""
@property
def json(self):
""""""
class Serializer(with_metaclass(SerializerMeta, BaseSerializer)):
pass
# compat.py
def with_metaclass(meta, *bases):
'''Defines a metaclass.
Creates a dummy class with a dummy metaclass. When subclassed, the dummy
metaclass is used, which has a constructor that instantiates a
new class from the original parent. This ensures that the dummy class and
dummy metaclass are not in the inheritance tree.
Credit to Armin Ronacher.
'''
class metaclass(meta):
__call__ = type.__call__
__init__ = type.__init__
def __new__(cls, name, this_bases, d):
if this_bases is None:
return type.__new__(cls, name, (), d)
return meta(name, bases, d)
return metaclass('temporary_class', None, {})
可能之前有过元编程经验的人就会发现这段代码很熟悉,Serializer 类定义时使用 with_metaclass 方法传入 SerializerMeta 元类和 BaseSerializer 基类,而 with_metaclass 是一个比较重要的方法,用来兼容 python2 和 python3 元类使用上的区别。
- with_metaclass 函数中定义了一个内部类(metaclass),并使用该内部类创建一个临时类 temporary_class
- 该临时类是 内部类(metaclass) 的实例(元类创建出来的类就是元类的实例), 即是 tempoary_class 类的元类是 metaclass
- 通过上面代码可以看出临时类创建时仅仅调用了
type.__new__
方法
当定义 Serializer 类的时候,Serializer 得到了继承的元类metaclass:
- 实例化 metaclass, 调用
metaclass.__new__
方法,即是调用 meta(name, bases, d), meta 就是 SerializerMeta 元类,bases 就是 BaseSerializer 基类(要继承的类) - 调用 SerializerMeta 元类的
__new__
方法来实例化得到 Serializer
这个地方需要注意一点是:
1、在定义 Serializer 类的时候,会执行 SerializerMeta 元类的__new__ 来创建类,而不是实例化的时候执行__new__ ,这是因为在类的定义(创建)过程中,是通过寻找 __metaclass__ 来完成的
2、上面虽然没有显示定义 __metaclass__ ,但由于下面metaclass的规则,会将定义的 SerializerMeta 类作为 metaclass 来创建类
3、metaclass 查找的规则是:如果当前类没有__metaclass__,但有基类,那么就使用第一个基类的__class__作为 __metaclass__,如果没有 __class__,则使用type 来创建类
一个简单的例子来看看:
# -*- coding: utf-8 -*-
from datetime import datetime
from marshmallow import Serializer, fields
class Person(object):
def __init__(self, name):
self.name = name
self.date_born = datetime.now()
class PersonSerializer(Serializer):
name = fields.String()
date_born = fields.DateTime()
person = Person(name="guoweikuang")
serialized = PersonSerializer(person)
print(PersonSerializer.__mro__)
# out: (, , , )
可以看到 PersonSerializer 继承链中没有之前创建的临时类(tempoary_class)