How can we use dict similar to the following?
dict[%s] % variable
For those who are interested in what I am trying to do exactly, I have three dicts:
dict_1 = {'a':'123', 'b':'234', 'c':'345'}
dict_2 = {'d':'456', 'e':'567', 'f':'678'}
dict_3 = {'a':'e', 'b':'d', 'c':'f'}
And I have a function where I need to input something like:
function(dict_1['a'], dict_2['e']) #according to dict_3 that 'a' is paired with 'e'.
Edited:
I was trying to write a for loop to loop over all the dicts and have them pair dict_1 and dict_2 pairs into the function according to dict_3. I actually don't need the %s thing after looking at you guys answer. That's what happens what you try to code without coffee in the morning lol.
And in the end, this following did what I wanted, thanks all!:
for i in dict_1:
results = function(dict_1[i],dict_2[dict_3[i]]
If what I gather is correct, you were almost already on the money. You can just write it like this:
dict["%s" % variable]
One issue with this, however, is that if you had something like:
d = {3 : 'hello'}
my_key = 3
d['%s' % my_key]
That would fail with a KeyError
Regardless though, it is kind of a roundabout way to use it. You can just write:
dict[otherdict['a']]
function(dict_1['a'], dict_2[dict_3['a']])
should work.
So i'd do something like
k = 'a'
function(dict_1[k],dict_2[dict_3[k]])
Using the % operator here doesn't make much sense to me because you're not trying to produce a string with some static data and a variably inserted value.
Because % operator is evaluated before than [] operator. You should do dict["%s" % variable] or more easier dict[variable] if variable is already a string.
If your variables are strings, you then use them as keys directly
dict[variable]
For the function you want to do, you can call
function(dict1[variable], dict2[dict3[variable]])
If you are trying to call this function for every key and value in dict3, you may want to just iterate over dict3.
for key, val in dict3.items():
function(dict1[key], dict2[values])
For a more pythonic way of collecting these results into a list
func_results = [function(dict1[key], dict2[val]) for key, val in dict3.items()]
One final thing. If you just have dict3 there for the purpose of this function call, a list of tuples is all you need:
arg_list = [('a', 'e'), ('b', 'd'), ('c', 'f')]
func_results = [function(dict1[arg1], dict2[arg2]) for arg1, arg2 in arg_list]
Note that if the keys were integers instead of strings, you will have to do:
dict[int("%d" % some_integer)]
Related
In a directory images, images are named like - 1_foo.png, 2_foo.png, 14_foo.png, etc.
The images are OCR'd and the text extract is stored in a dict by the code below -
data_dict = {}
for i in os.listdir(images):
if str(i[1]) != '_':
k = str(i[:2]) # Get first two characters of image name and use as 'key'
else:
k = str(i[:1]) # Get first character of image name and use 'key'
# Intiates a list for each key and allows storing multiple entries
data_dict.setdefault(k, [])
data_dict[k].append(pytesseract.image_to_string(i))
The code performs as expected.
The images can have varying numbers in their name ranging from 1 to 99.
Can this be reduced to a dictionary comprehension?
No. Each iteration in a dict comprehension assigns a value to a key; it cannot update an existing value list. Dict comprehensions aren't always better--the code you wrote seems good enough. Although maybe you could write
data_dict = {}
for i in os.listdir(images):
k = i.partition("_")[0]
image_string = pytesseract.image_to_string(i)
data_dict.setdefault(k, []).append(image_string)
Yes. Here's one way, but I wouldn't recommend it:
{k: d.setdefault(k, []).append(pytesseract.image_to_string(i)) or d[k]
for d in [{}]
for k, i in ((i.split('_')[0], i) for i in names)}
That might be as clean as I can make it, and it's still bad. Better use a normal loop, especially a clean one like Dennis's.
Slight variation (if I do the abuse once, I might as well do it twice):
{k: d.setdefault(k, []).append(pytesseract_image_to_string(i)) or d[k]
for d in [{}]
for i in names
for k in i.split('_')[:1]}
Edit: kaya3 now posted a good one using a dict comprehension. I'd recommend that over mine as well. Mine are really just the dirty results of me being like "Someone said it can't be done? Challenge accepted!".
In this case itertools.groupby can be useful; you can group the filenames by the numeric part. But making it work is not easy, because the groups have to be contiguous in the sequence.
That means before we can use groupby, we need to sort using a key function which extracts the numeric part. That's the same key function we want to group by, so it makes sense to write the key function separately.
from itertools import groupby
def image_key(image):
return str(image).partition('_')[0]
images = ['1_foo.png', '2_foo.png', '3_bar.png', '1_baz.png']
result = {
k: list(v)
for k, v in groupby(sorted(images, key=image_key), key=image_key)
}
# {'1': ['1_foo.png', '1_baz.png'],
# '2': ['2_foo.png'],
# '3': ['3_bar.png']}
Replace list(v) with list(map(pytesseract.image_to_string, v)) for your use-case.
Let's say we have a Python dictionary d, and we're iterating over it like so:
for k, v in d.iteritems():
del d[f(k)] # remove some item
d[g(k)] = v # add a new item
(f and g are just some black-box transformations.)
In other words, we try to add/remove items to d while iterating over it using iteritems.
Is this well defined? Could you provide some references to support your answer?
See also How to avoid "RuntimeError: dictionary changed size during iteration" error? for the separate question of how to avoid the problem.
Alex Martelli weighs in on this here.
It may not be safe to change the container (e.g. dict) while looping over the container.
So del d[f(k)] may not be safe. As you know, the workaround is to use d.copy().items() (to loop over an independent copy of the container) instead of d.iteritems() or d.items() (which use the same underlying container).
It is okay to modify the value at an existing index of the dict, but inserting values at new indices (e.g. d[g(k)] = v) may not work.
It is explicitly mentioned on the Python doc page (for Python 2.7) that
Using iteritems() while adding or deleting entries in the dictionary may raise a RuntimeError or fail to iterate over all entries.
Similarly for Python 3.
The same holds for iter(d), d.iterkeys() and d.itervalues(), and I'll go as far as saying that it does for for k, v in d.items(): (I can't remember exactly what for does, but I would not be surprised if the implementation called iter(d)).
You cannot do that, at least with d.iteritems(). I tried it, and Python fails with
RuntimeError: dictionary changed size during iteration
If you instead use d.items(), then it works.
In Python 3, d.items() is a view into the dictionary, like d.iteritems() in Python 2. To do this in Python 3, instead use d.copy().items(). This will similarly allow us to iterate over a copy of the dictionary in order to avoid modifying the data structure we are iterating over.
I have a large dictionary containing Numpy arrays, so the dict.copy().keys() thing suggested by #murgatroid99 was not feasible (though it worked). Instead, I just converted the keys_view to a list and it worked fine (in Python 3.4):
for item in list(dict_d.keys()):
temp = dict_d.pop(item)
dict_d['some_key'] = 1 # Some value
I realize this doesn't dive into the philosophical realm of Python's inner workings like the answers above, but it does provide a practical solution to the stated problem.
The following code shows that this is not well defined:
def f(x):
return x
def g(x):
return x+1
def h(x):
return x+10
try:
d = {1:"a", 2:"b", 3:"c"}
for k, v in d.iteritems():
del d[f(k)]
d[g(k)] = v+"x"
print d
except Exception as e:
print "Exception:", e
try:
d = {1:"a", 2:"b", 3:"c"}
for k, v in d.iteritems():
del d[f(k)]
d[h(k)] = v+"x"
print d
except Exception as e:
print "Exception:", e
The first example calls g(k), and throws an exception (dictionary changed size during iteration).
The second example calls h(k) and throws no exception, but outputs:
{21: 'axx', 22: 'bxx', 23: 'cxx'}
Which, looking at the code, seems wrong - I would have expected something like:
{11: 'ax', 12: 'bx', 13: 'cx'}
Python 3 you should just:
prefix = 'item_'
t = {'f1': 'ffw', 'f2': 'fca'}
t2 = dict()
for k,v in t.items():
t2[k] = prefix + v
or use:
t2 = t1.copy()
You should never modify original dictionary, it leads to confusion as well as potential bugs or RunTimeErrors. Unless you just append to the dictionary with new key names.
This question asks about using an iterator (and funny enough, that Python 2 .iteritems iterator is no longer supported in Python 3) to delete or add items, and it must have a No as its only right answer as you can find it in the accepted answer. Yet: most of the searchers try to find a solution, they will not care how this is done technically, be it an iterator or a recursion, and there is a solution for the problem:
You cannot loop-change a dict without using an additional (recursive) function.
This question should therefore be linked to a question that has a working solution:
How can I remove a key:value pair wherever the chosen key occurs in a deeply nested dictionary? (= "delete")
Also helpful as it shows how to change the items of a dict on the run: How can I replace a key:value pair by its value wherever the chosen key occurs in a deeply nested dictionary? (= "replace").
By the same recursive methods, you will also able to add items as the question asks for as well.
Since my request to link this question was declined, here is a copy of the solution that can delete items from a dict. See How can I remove a key:value pair wherever the chosen key occurs in a deeply nested dictionary? (= "delete") for examples / credits / notes.
import copy
def find_remove(this_dict, target_key, bln_overwrite_dict=False):
if not bln_overwrite_dict:
this_dict = copy.deepcopy(this_dict)
for key in this_dict:
# if the current value is a dict, dive into it
if isinstance(this_dict[key], dict):
if target_key in this_dict[key]:
this_dict[key].pop(target_key)
this_dict[key] = find_remove(this_dict[key], target_key)
return this_dict
dict_nested_new = find_remove(nested_dict, "sub_key2a")
The trick
The trick is to find out in advance whether a target_key is among the next children (= this_dict[key] = the values of the current dict iteration) before you reach the child level recursively. Only then you can still delete a key:value pair of the child level while iterating over a dictionary. Once you have reached the same level as the key to be deleted and then try to delete it from there, you would get the error:
RuntimeError: dictionary changed size during iteration
The recursive solution makes any change only on the next values' sub-level and therefore avoids the error.
I got the same problem and I used following procedure to solve this issue.
Python List can be iterate even if you modify during iterating over it.
so for following code it will print 1's infinitely.
for i in list:
list.append(1)
print 1
So using list and dict collaboratively you can solve this problem.
d_list=[]
d_dict = {}
for k in d_list:
if d_dict[k] is not -1:
d_dict[f(k)] = -1 # rather than deleting it mark it with -1 or other value to specify that it will be not considered further(deleted)
d_dict[g(k)] = v # add a new item
d_list.append(g(k))
Today I had a similar use-case, but instead of simply materializing the keys on the dictionary at the beginning of the loop, I wanted changes to the dict to affect the iteration of the dict, which was an ordered dict.
I ended up building the following routine, which can also be found in jaraco.itertools:
def _mutable_iter(dict):
"""
Iterate over items in the dict, yielding the first one, but allowing
it to be mutated during the process.
>>> d = dict(a=1)
>>> it = _mutable_iter(d)
>>> next(it)
('a', 1)
>>> d
{}
>>> d.update(b=2)
>>> list(it)
[('b', 2)]
"""
while dict:
prev_key = next(iter(dict))
yield prev_key, dict.pop(prev_key)
The docstring illustrates the usage. This function could be used in place of d.iteritems() above to have the desired effect.
I have a list like this-
send_recv_pairs = [(['produce_send'], ['consume_recv']), (['Send'], ['Recv']), (['sender2'], ['receiver2'])]
I want something like
[ {['produce_send']:['consume_recv']},{['Send']:['Recv']},{['sender2']:['receiver2']}
How to do this?
You can not use list as the key of dictionary.
This Article explain the concept,
https://wiki.python.org/moin/DictionaryKeys
To be used as a dictionary key, an object must support the hash function (e.g. through hash), equality comparison (e.g. through eq or cmp), and must satisfy the correctness condition above.
And
lists do not provide a valid hash method.
>>> d = {['a']: 1}
TypeError: unhashable type: 'list'
If you want to specifically differentiate the key values you can use tuple as they hash able
{ (i[0][0], ): (i[1][0], ) for i in send_recv_pairs}
{('Send',): ('Recv',),
('produce_send',): ('consume_recv',),
('sender2',): ('receiver2',)}
You can't have lists as keys, only hashable types - strings, numbers, None and such.
If you still want to use a dictionary knowing that, then:
d={}
for tup in send_recv_pairs:
d[tup[0][0]]=tup[1]
If you want the value to be string as well, use tup[1][0] instead of tup[1]
As a one liner:
d={tup[0][0]]:tup[1] for tup in list} #tup[1][0] if you want values as strings
You can check it over here, in the second way of creating distionary.
https://developmentality.wordpress.com/2012/03/30/three-ways-of-creating-dictionaries-in-python/
A Simple way of doing it,
First of all, your tuple is tuple of lists, so better change it to tuple of strings (It makes more sense I guess)
Anyway simple way of working with your current tuple list can be like :
mydict = {}
for i in send_recv_pairs:
print i
mydict[i[0][0]]= i[1][0]
As others pointed out, you cannot use list as key to dictionary. So the term i[0][0] first takes the first element from the tuple - which is a list- and then the first element of list, which is the only element anyway for you.
Do you mean like this?
send_recv_pairs = [(['produce_send'], ['consume_recv']),
(['Send'], ['Recv']),
(['sender2'], ['receiver2'])]
send_recv_dict = {e[0][0]: e[1][0] for e in send_recv_pairs}
Resulting in...
>>> {'produce_send': 'consume_recv', 'Send': 'Recv', 'sender2': 'receiver2'}
As mentioned in other answers, you cannot use a list as a dictionary key as it is not hashable (see links in other answers).
You can therefore just use the values in your lists (assuming they stay as simple as in your example) to create the following two possibilities:
send_recv_pairs = [(['produce_send'], ['consume_recv']), (['Send'], ['Recv']), (['sender2'], ['receiver2'])]
result1 = {}
for t in send_recv_pairs:
result1[t[0][0]] = t[1]
# without any lists
result2 = {}
for t in send_recv_pairs:
result2[t[0][0]] = t[1][0]
Which respectively gives:
>>> result1
{'produce_send': ['consume_recv'], 'Send': ['Recv'], 'sender2': ['receiver2']}
>>> result2
{'produce_send': 'consume_recv', 'Send': 'Recv', 'sender2': 'receiver2'}
Try like this:
res = { x[0]: x[1] for x in pairs } # or x[0][0]: x[1][0] if you wanna store inner values without list-wrapper
It's for Python 3 and when keys are unique. If you need collect list of values per key, instead of single value, than you may use something like itertools.groupby or map+reduce. Wrote about this in comments and I'll provide example.
And yes, list cannot store key-values, only dict's, but maybe it's just typo in question.
You can not use list as the dictionary key, but instead you may type-cast it as tuple to create the dict object.
Below is the sample example using a dictionary comprehension:
>>> send_recv_pairs = [(['produce_send'], ['consume_recv']), (['Send'], ['Recv']), (['sender2'], ['receiver2'])]
>>> {tuple(k): v for k, v in send_recv_pairs}
{('sender2',): ['receiver2'], ('produce_send',): ['consume_recv'], ('Send',): ['Recv']}
For details, take a look at: Why can't I use a list as a dict key in python?
However if your nested tuple pairs were not list, but any other hashable object pairs, you may have type-casted it to dict for getting the desired result. For example:
>>> my_list = [('key1', 'value1'), ('key2', 'value2')]
>>> dict(my_list)
{'key1': 'value1', 'key2': 'value2'}
This question already has answers here:
Destructuring-bind dictionary contents
(17 answers)
Closed 1 year ago.
I am studying Python and currently going through some more learning with dictionaries.
I was wondering;
If I have a dictionary like: d = {'key_1': 'value_a', 'key_2': 'value_b'} and I want separate/divide this dictionary into variables where each variable is a key from the dictionary and each variables value is the value of that key in the dictionary.
What would be the best pythonic way to achieve this?
d = {'key_1': 'value_a', 'key_2': 'value_b'}
#perform the command and get
key_1 = 'value_a'
key_2 = 'value_b'
I tried: key_1, key_2 = d but it did not work.
Basically I am seeking expert's wisdom to find out if there is a better way to reduce 2 lines of code into one.
Note: This is not a dynamic variable creation.
The existing answers will work, but they're all essentially re-implementing a function that already exists in the Python standard library: operator.itemgetter()
From the docs:
Return a callable object that fetches item from its operand using the operand’s __getitem__() method. If multiple items are specified, returns a tuple of lookup values. For example:
After f = itemgetter(2), the call f(r) returns r[2].
After g = itemgetter(2, 5, 3), the call g(r) returns (r[2], r[5], r[3]).
In other words, your destructured dict assignment becomes something like:
from operator import itemgetter
d = {'key_1': 'value_a', 'key_2': 'value_b'}
key_1, key_2 = itemgetter('key_1', 'key_2')(d)
# prints "Key 1: value_a, Key 2: value_b"
print("Key 1: {}, Key 2: {}".format(key_1, key_2))
Problem is that dicts are unordered, so you can't use simple unpacking of d.values(). You could of course first sort the dict by key, then unpack the values:
# Note: in python 3, items() functions as iteritems() did
# in older versions of Python; use it instead
ds = sorted(d.iteritems())
name0, name1, name2..., namen = [v[1] for v in ds]
You could also, at least within an object, do something like:
for k, v in dict.iteritems():
setattr(self, k, v)
Additionally, as I mentioned in the comment above, if you can get all your logic that needs your unpacked dictionary as variables in to a function, you could do:
def func(**kwargs):
# Do stuff with labeled args
func(**d)
A solution which has not been mentionned before would be
dictget = lambda d, *k: [d[i] for i in k]
and then use it:
key_1, key_2 = dictget(d, 'key_1', 'key_2')
whose advantage is that it is quite readable even with more variables to be retrieved.
Even more readable, however, would be a "real" function such as
def dictget(d, *k):
"""Get the values corresponding to the given keys in the provided dict."""
return [d[i] for i in k]
# or maybe
return (d[i] for i in k) # if we suppose that we have bigger sets of result
# or, equivalent to this
for i in k:
yield d[i]
which as well supports commenting with a docstring and is to be preferred.
var1, var2 = (lambda key1, key2: (key1, key2))(**d)
If you want to give anyone reading your code a headache you can use anonymous function to unpack values like this.
You can do this, if you're brave:
for k, v in d.items():
locals()[k] = v
But being brave might not be enough - you might also have to be reckless etc.
If you want to be a reckless hero like #ecatmur, you can do this:
locals().update(d)
But now that OP has updated his question and answered comments, it seems, this isn't what he really wants to do. Just for the record: There are good reasons for dynamically creating variables - even if everyone here agrees that it's not pythonic. A lot of interpreter style problems can be solved neetly with dynamic altering of your scope. Just do this in a controlled fashion. And... uh, don't deploy this to some production site ;)
I actually have a usecase, where i pull all the arguments of an __init__ method into the self namespace on object construction:
vars(self).update(somedict)
The vars function gets you a dict of the “namespace” associated with the object passed. However, this will not work with locals in a function, due to CPython implementation details. So it's not supposed to work on all interpreters.
For global namespace you would substitute vars(self) with globals(), but this is really a sign that something is wrong with your logic. As said, for local variables this won't work anyways (It'll NameError even if you assigned a value to the dict).
i think this should solve your problem
d = {'key_1': 'value_a', 'key_2': 'value_b'}
for k,v in d.items():
exec '%s=%s'%(k,v)
#glglgl's answer is not most voted, that answer worked for me,
solution1={'variable': np.array([75, 74]), 'function': 0}
def dict_get(d, *k):
for i in k:
yield d[i]
variables, obj_func = dict_get(solution1, 'variable', 'function')
a, b=variables
print(a)
reference: #glglgl
It's not recommended to ever declare variables dynamically, because it becomes very difficult to find the source of a variable name. That said, it's possible to hack together a solution Dynamic variable name in python but I wouldn't recommend it. Probably better off using a plain old dictionary.
Here is a solution that uses Python's inspect module on the calling stack frame to determine how to extract the right values from a supplied dictionary. Right now the only check is to make sure that there is a value available for each of the output variables, but feel free to add additional checks if you need them.
import inspect
def update(src):
result = []
cprev = inspect.currentframe().f_back
#print(cprev.f_code.co_names)
for v in cprev.f_code.co_names[1:]:
if src is cprev.f_locals[v]: continue
if v in src:
result.append(src[v])
else:
raise NameError(v + " has no source for update")
return result
Usage looks like this:
src={'a': 1, 'b': 2, 'c': 3}
a,b,c = update(src)
For instance,
if dict['sample']:
//append values to dict['sample']
else:
// assign new key to the python dictionary
If dict['sample'] is empty, Python will throw errors. Does anyone know a better way to check on this?
All I want is something like that, I will have list of data, let's say a,a,b,c,g,g,g,g,g.
So, I want python dictionary to append the values of two a,a to dict['a'], and g,g,g,g,g to dict['g'] and so the rest as dict['b'] etc. A for loop will be executed to loop through the data of a,a,b,c,g,g,g,g,g.
I hope I've made my question clear. Any idea? Preferably, if Python's dictionary has a way to check existing key.
EDIT
Credit goes to #Paul McGuire. I've figured out the exact solution I wanted based on #Paul McGuire's answer. As shown below:
from collections import defaultdict
class Test:
def __init__(self, a,b):
self.a=a
self.b=b
data = []
data.append(Test(a=4,b=6))
data.append(Test(a=1,b=2))
data.append(Test(a=1,b=3))
data.append(Test(a=2,b=2))
data.append(Test(a=3,b=2))
data.append(Test(a=4,b=5))
data.append(Test(a=4,b=2))
data.append(Test(a=1,b=2))
data.append(Test(a=5,b=9))
data.append(Test(a=4,b=7))
dd = defaultdict(list)
for c in data:
dd[c.a].append(c.b)
print dd
The old approaches of "if key in dict" or "dict.get" or "dict.setdefault" should all be set aside in favor of the now standard defaultdict:
data = "aabcggggg"
from collections import defaultdict
dd = defaultdict(list)
for c in data:
dd[c].append(c)
print dd
defaultdict takes care of the checking for key existence for you, all your code has to do is 1) define a factory function or class for the defaultdict to use to initialize a new key entry (in this case, defaultdict(list)), and 2) define what to do with each key (dd[c].append(c)). Clean, simple, no clutter.
In your particular example, you could actually use itertools.groupby, since the groups of letters are all contiguous for each grouping value. groupby returns an iterator of tuples, each tuple containing the current key value and an iterator of the matching values. The following code works by converting each tuple's list-of-values-iterator to an actual list (in list(v)), and passing the sequence of key-valuelist tuples to the dict constructor.
from itertools import groupby
print dict((k,list(v)) for k,v in groupby(data))
prints:
{'a': ['a', 'a'], 'c': ['c'], 'b': ['b'], 'g': ['g', 'g', 'g', 'g', 'g']}
my_dict = {}
my_dict.setdefault('sample', []).append(value)
second parameter of 'setdefault' method says what should be initial value if given key does not exist
If I understand your values are lists.
if 'sample' in mydict:
pass #whatever
else:
mydict['sample'] = []
What you want to do is the following:
A = ['a','a','b','b','b','c','c','c']
myDict = {}
for i in A:
if i not in myDict:
myDict[i] = []
myDict[i].append(i)
print myDict
Every dict key should contain a list. Am I right?
d = dict()
try:
d['sample'].append(new_data)
except KeyError:
d['sample'] = [new_data]
I believe this would work. By the way, you shouldn't use the name dict for a dictonary. dict is already used as a function.
Edit1:
I'm not really sure I understand what you trying to do. Nor do I know if my solution is the best of those proposed. But is it this you are trying to do? It seems a little bit odd? Or do you want to count how many times every letter occur?
# Create a list named l.
l = ['a', 'a', 'b', 'c', 'g', 'g', 'g', 'g','g']
# Create dictionary named d.
d = dict()
for i in l:
try:
d[i].append(i)
except KeyError:
d[i] = [i]
If you are using some very old python:
if not myDict.has_key(key):
myDict[key]=[val]
else:
myDict[key].append(val)
Recently the has_key has been deprecated in favor of key in dict
So nowadays, it would be:
if not key in myDict:
myDict[key]=[val]
else:
myDict[key].append(val)
Credit should goes to #Niclas Nilsson even though his posted solution didn't really worked for what I wanted, however, it did help me figure out the solution that I wanted in the simplest form.
Still, I appreciate everyone's help here for extra knowledge and alternative ways of solving it. Thanks a lot.
Following achieved what I wanted in the simplest way without additional library imported etc:
r = {}
try:
if r['new_data']:
r['new_data'] = 'appending'
except KeyError:
r['new_data'] = 'new value'
print r['new_data']
The exact solution I wanted the most as shown below. Credit goes to #Paul McGuire
from collections import defaultdict
class Test:
def __init__(self, a,b):
self.a=a
self.b=b
data = []
data.append(Test(a=4,b=6))
data.append(Test(a=1,b=2))
data.append(Test(a=1,b=3))
data.append(Test(a=2,b=2))
data.append(Test(a=3,b=2))
data.append(Test(a=4,b=5))
data.append(Test(a=4,b=2))
data.append(Test(a=1,b=2))
data.append(Test(a=5,b=9))
data.append(Test(a=4,b=7))
dd = defaultdict(list)
for c in data:
dd[c.a].append(c.b)
print dd