Related Entries

India PyCon 2009
Quick wallpaper changer
Load testing with Grinder
Adding namespace to XML
Opera RSS to OPML

« Exuberant ctags and Vim
» Joy of python: dir, help and pprint

Joy of Python: Classes and Dictionaries

I must warn you, this is silly! But, it helps me while writing consistent test scripts.

Python makes pretty good use of dictionaries in its implementation of classes. Some times, it is much more pleasant to express things in object.attribute form rather than like dictionary['key']. Here is a simple and useless python script that might give you some idea about converting classes to dictionaries and making classes out of dictionaries.

"""
Examples to convert back and forth between classes and dictionaries

S Babu:
Joys of python: is a series of small and often silly scripts using
python that does something while explaining some nice features of
python. Absolutely newbie material.

http://vsbabu.org/mt/archives/categories/python/

All small values of joy are marked by comments starting with #joy:
"""   

import types

def class2dict(o):
    """Return a dictionary from object that has public
       variable -> key pairs
    """    
    dict = {}
    #Joy: all the attributes in a class are already in __dict__
    for elem in o.__dict__.keys():
        if elem.find("_" + o.__class__.__name__) == 0:
            continue
            #We discard private variables, which are automatically
            #named _ClassName__variablename, when we define it in
            #the class as __variablename
        else:
            dict[elem] = o.__dict__[elem]
    return dict

def dict2class(d):
    """Return a class that has same attributes/values and
       dictionaries key/value
    """
    
    #see if it is indeed a dictionary
    if type(d) != types.DictType:
        return None
    
    #define a dummy class
    class Dummy:
        pass
        
    c = Dummy
    for elem in d.keys():
        c.__dict__[elem] = d[elem]
    return c

#Joy: we can write our testers here
if __name__ == '__main__':
    
    class MyClass:
        """A sample class definition"""
        def __init__(self):
            self.original = "hello world"
            self.__private = "private"
            self.__hell__ = 134
        def hello(self):
            print self.original
      
    mc = MyClass()
    mc.new = "new world"  
    d = class2dict(mc)
    print d
    
    employee = dict2class( {'name':'dilbert',
                    'iq': 30,
                    'department':'hr',
                    'supervisor':'dogbert' } )
    print employee.__dict__
  1. Attribute-style access is so lovely I often start off classes as a descendant of object with no definition (``pass``), just to give me something I can use attribute-style access with rather than dict-style access.

    Posted by: Garth T Kidd on February 13, 2003 08:46 PM
  2. BTW: In dict2class, I'd eliminate the loop with either of the following:

    # single-call update
    c.__dict__.update(d)
    # or, assign to __dict__
    c.__dict__ = d.copy()

    (If you don't copy, you'll end up with shared state, which is sometimes useful -- check out the Singleton pattern in the ASPN cookbook.)

    In class2dict I'd precompute: privatePrefix = '_' + o.__class__.__name__
    and then use elem.startswith(privatePrefix) as the comparison. Or, you could use list comprehensions to reduce the entire function to one line:

    return dict([(k, v) for (k, v) in o.__dict__.items if not k.startswith('_'+o.__class__.__name__)])

    To make long list comprehensions readable, I sometimes break the line before the 'for' (especially if the expression before it is big), the 'in' (especially if the expression producing the sequence is big), and the 'if' (especially if the test expression is big). In this case, I'd only do it before the 'if'.

    Posted by: Garth T Kidd on February 13, 2003 09:14 PM
  3. Thanks Garth.

    Personally, I try not to use list comprehensions as much - it reminds me too much of my Perl days :-)

    Posted by: Babu on February 13, 2003 09:57 PM
//-->