Guy Dafny
Guy Dafny

Reputation: 1829

Struct-like in python

Using Python, I'm trying to write object that it's access would be like this:

page[2].records[7].color = "ffff"

(the 'record' has some fields).

the object should be exported to json string and of course import from json (currently unwrittten), so I've added the toString() method.

The point is the code is very "clumsy". Is there way (using python) to make more "comely" code?

my code:

class Record ():
    '''
    '''
    def __init__(self, title, color, action, data) :
        self.title = title
        self.color = color
        self.action = action
        self.data = data
    def toDict(self) :
        ans = {'title':self.title, 'color':self.color, 'action':self.action, 'data':self.data}
        return ans
    def toString(self):
        return '%s' % self.toDict()
#-----------------------------------------------------------------------
class Records():
    '''
    '''
    def __init__(self):
        self.f_record = {}
    def __getitem__(self, key):
        if not(self.f_record.get(key,None)):
            self.f_record[key] = Record(None,None,None,None)
        return self.f_record[key]
    def __setitem__(self, key, value):
        self.f_record[key] = value
    def toDict(self):
        ans = {}
        for i in self.f_record:
            ans[i] = self.f_record[i].toString()
        return ans
    def toString(self):
        return '%s' % self.toDict()
#-----------------------------------------------------------------------
class Page():
    '''
    '''
    def __init__(self):
        self.records = Records()
    def toString(self):
        return self.records.toString()
#-----------------------------------------------------------------------
class Papers():
    '''
    '''
    def __init__(self):
        self.f_papers = {}
    def __getitem__(self,key):
        if not (self.f_papers.get(key,None)):
            self.f_papers[key] = Page()
        return self.f_papers[key]
    def toString(self):
        ans = {}
        for i in self.f_papers:
            ans[i] = self.f_papers[i].toString()
        return '%s' % ans
#-----------------------------------------------------------------------
#tests

a = Papers()
a[1].records[1] = Record('group','red','open', 'group1')
a[1].records[2] = Record('group','green','open', 'group2')

a[2].records[7].title = "ffff"
a[1].records[1].title = 'title :-) '

print a[1].records[1].toString()
print a.toString()

Upvotes: 0

Views: 158

Answers (2)

poke
poke

Reputation: 388233

You could use dict itself to make it a bit easier:

from collections import defaultdict

class PropertyDict (dict):
    def __getattr__ (self, attr):
        if self.has_key(attr):
            return self.__getitem__(attr)
        return object.__getattr(self, attr)

    def __setattr__ (self, attr, value):
        self.__setitem__(attr, value)

class Record (PropertyDict):
    def __init__ (self, title = None, color = None, action = None, data = None):
        self.title = title
        self.color = color
        self.action = action
        self.data = data

class Page (PropertyDict):
    def __init__ (self):
        self.records = defaultdict(Record)

papers = defaultdict(Page)
papers[1].records[1] = Record('group', 'red', 'open', 'group1')
papers[1].records[2] = Record('group', 'green', 'open', 'group2')

papers[2].records[7].title = "ffff"
papers[1].records[1].title = 'title :-) '

print(papers[1].records[1])
print(papers)

As the objects are now subtypes of dict, serializing it with json is simple. Only for deserializing you would have to write your own encode handler.

Upvotes: 1

jfs
jfs

Reputation: 414745

To serialize your object to json:

import json

json_text = json.dumps(your_obj.as_dict())

To create your object from json:

obj = YourClass.from_dict(json.loads(json_text))

You could easily implement the methods:

class YourClass(object):
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)
    @classmethod
    def from_dict(cls, attrs):
        return cls(**attrs)
    def as_dict(self):
        return dict(self.__dict__)
    def __str__(self):
        return json.dumps(self.as_dict())
    def __repr__(self):
        # see http://docs.python.org/3/library/types.html#types.SimpleNamespace
        d = self.as_dict()
        items = ("{}={!r}".format(k, d[k]) for k in sorted(d))
        return "{}({})".format(type(self).__name__, ", ".join(items))

Example:

>>> obj = YourClass(title="foo", name="bar")
>>> obj.color = "ffffff"
>>> obj.name
'bar'
>>> obj
YourClass(color='ffffff', name='bar', title='foo')
>>> print(obj)
{"name": "bar", "color": "ffffff", "title": "foo"}
>>> obj.as_dict()
{'name': 'bar', 'color': 'ffffff', 'title': 'foo'}

You could define from_json, as_json methods if you'd like using the one-liners

Upvotes: 1

Related Questions