possible attribute-oriented class
Colin J. Williams
cjw at ncf.ca
Fri Sep 4 11:12:51 EDT 2009
Jan Kaliszewski wrote:
> [originally from python-list at python.org,
> crossposted to python-ideas at python.org]
>
> 04-09-2009 o 00:46:01 Ken Newton <krnewton at gmail.com> wrote:
>
>> I have created the following class definition with the idea of making
>> a clean syntax for non-programmers to created structured data within a
>> python environment.
>>
>> I would appreciate comments on this code. First, is something like
>> this already done? Second, are there reasons for not doing this? If
>> this seems OK, how could I clean up the string conversion to have
>> indented format.
>>
>> The expected use would have all items in the structure be simple
>> python types or AttrClass types. Code written in python could walk the
>> structure in a simple way to locate any desired values. Code in a
>> C/C++ extension should also be able to walk the structure to use any
>> value in the structure.
>>
>> class AttrClass(object):
>> """AttrClass lets you freely add attributes in nested manner"""
>>
>> def __init__(self):
>> pass
>> def __setitem__(self, key, value):
>> return self.__dict__.__setitem__(key, value)
>> def __repr__(self):
>> return "%s(%s)" % (self.__class__.__name__,
>> self.__dict__.__repr__())
>> def __str__(self):
>> ll = ['{']
>> for k,v in self.__dict__.iteritems():
>> ll.append("%s : %s" % (k, str(v)))
>> return '\n'.join(ll) + '}'
> [snip]
>
> I find the idea interesting and close to my own needs in many
> situations, if I could alter it a bit.
>
> Of course, we always can use an empty class ('class MyStruct: pass')
> or simply use a dict... But both methods are inconvinient in some
> ways.
>
> In the case of dict we are convicted -- even when we need static
> access -- to mapping notation (obj['member']) which is less
> convenient and (what's more important) more error-prone than
> attribute dot-notation.
>
> In the case of empty class/object we can use convenient attr
> dot-notation but dynamic access is less natural...
>
> IMHO there could be -- in collections module or even as a built-in
> factory function -- something (somehow) similar to namedtuple, but
> mutable and more dict-like. I'am less focused on nesting such
> structures, and more on making it a namespace-like objects with
> convenience-and-today-usage features. Please consider the code:
>
>
> class AttrDict(dict): # (or maybe from OrderedDict)
> "It's only a model. (Shhh!)"
>
> def __getattr__(self, name):
> if name.startswith('_'):
> raise AttributeError("AttrDict's key can't "
> "start with underscore")
> else:
> return self[name]
>
> def __setattr__(self, name, value):
> self[name] = value
>
> def __delattr__(self, name):
> del self[name]
>
> def __repr__(self):
> return '{0}({1})'.format(self.__class__.__name__,
> dict.__repr__(self))
> def __str__(self):
> return self._as_str()
>
> def _gen_format(self, indwidth, indstate):
> indst = indstate * ' '
> ind = (indstate + indwidth) * ' '
> yield ('\n' + indst + '{' if indstate else '{')
> for key, val in self.items():
> valstr = (str(val) if not isinstance(val, AttrDict)
> else val._as_str(indwidth, indstate + indwidth))
> yield '{ind}{key}: {valstr}'.format(ind=ind, key=key,
> valstr=valstr)
> yield indst + '}'
>
> def _as_str(self, indwidth=4, indstate=0):
> return '\n'.join(self._gen_format(indwidth, indstate))
>
> def _as_dict(self):
> return dict.copy(self)
>
>
> # Test code:
> if __name__ == '__main__':
> struct = AttrDict()
> struct.first = 1
> struct.second = 2.0
> struct.third = '3rd'
> struct.fourth = [4]
> print(struct)
> # output:
> # {
> # 'second': 2.0
> # 'fourth': [4]
> # 'third': '3rd'
> # 'first': 1
> # }
>
> del struct.fourth
>
> print(repr(struct))
> # output:
> # AttrDict({'second': 2.0, 'third': '3rd', 'first': 1})
>
> print(struct.first) # (static access)
> # output:
> # 1
>
> for x in ('first', 'second', 'third'):
> print(struct[x]) # (dynamic access)
> # output:
> # 1
> # 2.0
> # 3rd
>
> struct.sub = AttrDict(a=1, b=2, c=89)
> print(struct._as_dict())
> # output:
> # {'second': 2.0, 'sub': AttrDict({'a': 1, 'c': 89, 'b': 2}),\
> # 'third': '3rd', 'first': 1}
>
> print(struct._as_str(8))
> # output:
> # {
> # second: 2.0
> # sub:
> # {
> # a: 1
> # c: 89
> # b: 2
> # }
> # third: 3rd
> # first: 1
> # }
>
>
> What do you think about it?
>
> Cheers,
> *j
>
I like both suggestions. The dot notation is simpler than the dictionary one,
in may cases.
struct is perhaps a name to avoid, as it is a standard module.
The result has similarities to the Pascal Record:
http://uva.ulb.ac.be/cit_courseware/pascal/pas048.htm
Colin W.
More information about the Python-list
mailing list