Skip to content

Instantly share code, notes, and snippets.

@riffm
Created June 22, 2009 13:50
Show Gist options
  • Save riffm/133971 to your computer and use it in GitHub Desktop.
Save riffm/133971 to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*-
class MultiValueDict(dict):
"""
Словарь с возможностью соответствия
нескольких значений одному ключу.
>>> list_ = (('foo','bar'),('spam','eggs'),('foo','baz'))
>>> md = MultiValueDict(list_)
>>> md['foo']
['bar', 'baz']
>>> md['spam']
['eggs']
>>> md.getlist('foo')
['bar', 'baz']
"""
def __init__(self, initial_data={}, *args, **kwargs):
"""
initial_data -> либо список кортежей
((key1, value1), (key2, value2), ...(key1, value2))
либо обычный словарь, либо экземпляр MultiValueDict
>>> list_ = (('foo','bar'),('spam','eggs'),('foo','baz'))
>>> md = MultiValueDict(list_)
>>> print md
MultiValueDict([('foo', 'bar'), ('foo', 'baz'), ('spam', 'eggs')])
>>> new_md = MultiValueDict(md)
>>> print new_md
MultiValueDict([('foo', 'bar'), ('foo', 'baz'), ('spam', 'eggs')])
"""
super(MultiValueDict, self).__init__(*args, **kwargs)
if hasattr(initial_data, 'items'):
# Предполагаем, что initial_data - словарь или экземпляр
# MultiValueDict. Просто сохранить копию словаря нельзя, потому что
# внутреннее представление данных - словарь, каждому
# ключу которого соответствует список значений
initial_data = initial_data.items()
for key, value in initial_data:
self.append(key, value)
def append(self, key, value):
"""
Метод добавляет значение ключу, при этом,
если ключа не существует, то он создается.
>>> md = MultiValueDict()
>>> md.append('foo', 'bar')
>>> md.append('foo', 'baz')
>>> md.append('spam', 'eggs')
>>> print md
MultiValueDict([('foo', 'bar'), ('foo', 'baz'), ('spam', 'eggs')])
"""
self.setdefault(key, []).append(value)
getlist = dict.__getitem__
def __setitem__(self, key, value):
"""
Метод принимает ключ и список или кортеж
значений.
>>> md = MultiValueDict()
>>> md['foo'] = 'bar'# doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
AssertionError: Values must be type list or tuple
>>> md['foo'] = ['spam', 'eggs']
>>> print md
MultiValueDict([('foo', 'spam'), ('foo', 'eggs')])
>>> md.setlist('foo', ['bar', 'baz'])
>>> print md
MultiValueDict([('foo', 'bar'), ('foo', 'baz')])
"""
assert isinstance(value, list),\
"Values must be type list"
super(MultiValueDict, self).__setitem__(key, value)
setlist = __setitem__
def items(self):
"""
Метод возвращает кортежи (key, value), если у
ключа несколько значений, то будет возвращено
несколько кортежей (key, value1), (key, value2)
>>> md = MultiValueDict()
>>> md['foo'] = ['bar','baz']
>>> md['spam'] = ['eggs',]
>>> md.items()
[('foo', 'bar'), ('foo', 'baz'), ('spam', 'eggs')]
"""
return list(self.iteritems())
def iteritems(self):
for k,v in super(MultiValueDict, self).iteritems():
for item in v:
yield (k, item)
def copy(self):
return self.__class__(self)
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self.items())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment