django 源码分析 - 自定义数据结构

django 自定义了一些数据结构,主要有 OrderedSet,MultiValueDict,ImmutableList,DictWrapper

0x01

OrderedSet

class OrderedSet(object):

    def __init__(self, iterable=None):
        self.dict = OrderedDict(((x, None) for x in iterable) if iterable else [])

    def add(self, item):
        self.dict[item] = None

    def remove(self, item):
        del self.dict[item]

    def discard(self, item):
        try:
            self.remove(item)
        except KeyError:
            pass

    def __iter__(self):
        return iter(self.dict.keys())

    def __contains__(self, item):
        return item in self.dict

    def __bool__(self):
        return bool(self.dict)

    def __nonzero__(self):      # Python 2 compatibility
        return type(self).__bool__(self)

    def __len__(self):
        return len(self.dict)

这里面最重要的其实就是 self.dict = OrderedDict(((x, None) for x in iterable) if iterable else []), 使用了 OrderedDict 有序字典 这个 python 标准库里面的数据结构,下面看下 self.dict 的返回形式

>>> from collections import OrderedDict
>>> iterable = [1,2,3]
>>> OrderedDict(((x, None) for x in iterable) if iterable else [])
OrderedDict([(1, None), (2, None), (3, None)])

0x02

MultiValueDict

MultiValueDict 在 http 请求参数处理的时候特别有用,因为有的时候传入的参数是一个数组,QueryDict 继承了 MultiValueDict, 来对参数进行处理,先贴下用法

    >>> d = MultiValueDict({'name': ['Adrian', 'Simon'], 'position': ['Developer']})
    >>> d['name']
    'Simon'
    >>> d.getlist('name')
    ['Adrian', 'Simon']
    >>> d.getlist('doesnotexist')
    []
    >>> d.getlist('doesnotexist', ['Adrian', 'Simon'])
    ['Adrian', 'Simon']
    >>> d.get('lastname', 'nonexistent')
    'nonexistent'
    >>> d.setlist('lastname', ['Holovaty', 'Willison'])

主要是实现了 getlist, setlist 方法, getlist 调用 getitem, getitem 当 key 不存在时,返回 []

def __getitem__(self, key):
        """
        Returns the last data value for this key, or [] if it's an empty list;
        raises KeyError if not found.
        """
        try:
            list_ = super(MultiValueDict, self).__getitem__(key)
        except KeyError:
            raise MultiValueDictKeyError(repr(key))
        try:
            return list_[-1]
        except IndexError:
            return []

0x03

ImmutableList

class ImmutableList(tuple):
    def __new__(cls, *args, **kwargs):
        if 'warning' in kwargs:
            warning = kwargs['warning']
            del kwargs['warning']
        else:
            warning = 'ImmutableList object is immutable.'
        self = tuple.__new__(cls, *args, **kwargs)
        self.warning = warning
        return self

    def complain(self, *wargs, **kwargs):
        if isinstance(self.warning, Exception):
            raise self.warning
        else:
            raise AttributeError(self.warning)

当这个数据结构的实例改变时,会提示一些有用的信息来提示用户这个类是不可变的

0x04

DictWrapper

主要是做了 dict 的封装

class DictWrapper(dict):
    def __init__(self, data, func, prefix):
        super(DictWrapper, self).__init__(data)
        self.func = func
        self.prefix = prefix
        
    def __getitem__(self, key):
        if key.startswith(self.prefix):
            use_func = True
            key = key[len(self.prefix):]
        else:
            use_func = False
        value = super(DictWrapper, self).__getitem__(key)
        if use_func:
            return self.func(value)
        return value

>>> def call_f(a):
...     return 'hello %s' % a
...
>> dict_wrapper = DictWrapper({'1': 'john'}, call_f, 'prefix_')
>>> dict_wrapper['prefix_1']
'hello john'

当出现 prefix 前缀时自动会去调用 func 返回结果

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 内置函数Python解释器内置了许多功能和类型,总是可用的。他们是按字母顺序列在这里。 abs(x)返回一个数的绝...
    uangianlap阅读 1,285评论 0 0
  • python学习笔记 声明:学习笔记主要是根据廖雪峰官方网站python学习学习的,另外根据自己平时的积累进行修正...
    renyangfar阅读 3,112评论 0 10
  • 教程总纲:http://www.runoob.com/python/python-tutorial.html 进阶...
    健康哥哥阅读 2,087评论 1 3
  • # 第一优先级规则声明: # 除了梦境,每一个意识主进程都必须与一个身体参与的机械进程相匹配,否则结束意识主进程。...
    李洞BarryLi阅读 3,941评论 0 1
  • 谁在 打磨一帘北方的雨 在幽幽的小径上抒写情诗 好想把你写在诗里 穿插在梨花带雨的梦境 听 琵琶也已奏响 ...
    我是深海精灵阅读 198评论 1 2