<top_posting><br>I like this version very much. I'm ready to put this into practice to see how it<br>works in practice.<br><br>A minor point: I envision this to be used in a context where all key values are <br>strings (legal attribute identifiers). But constructing an AttrClass from a dict <br>
or setting values directly with the dict syntax can allow any valid item as a<br>dict key -- specifically numbers, tuples, etc. If the user of this class chooses<br>to do this, a number of the items become inaccessible to the attribute syntax.<br>
In my case, I think this won't be a problem since I anticipate that values will<br>always be set by the attribute syntax, but it might be an issue for other uses.<br></top_posting><br><br><div class="gmail_quote">
On Fri, Sep 4, 2009 at 6:01 AM, Jan Kaliszewski <span dir="ltr"><<a href="mailto:zuo@chopin.edu.pl">zuo@chopin.edu.pl</a>></span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
[originally from <a href="mailto:python-list@python.org" target="_blank">python-list@python.org</a>,<br>
crossposted to <a href="mailto:python-ideas@python.org" target="_blank">python-ideas@python.org</a>]
<br></blockquote><div>[snip] </div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
class AttrDict(dict): # (or maybe from OrderedDict)<br>
"It's only a model. (Shhh!)"<br>
<br>
def __getattr__(self, name):<br>
if name.startswith('_'):<br>
raise AttributeError("AttrDict's key can't "<br>
"start with underscore")<br>
else:<br>
return self[name]<br>
<br>
def __setattr__(self, name, value):<br>
self[name] = value<br>
<br>
def __delattr__(self, name):<br>
del self[name]<br>
<br>
def __repr__(self):<br>
return '{0}({1})'.format(self.__class__.__name__,<br>
dict.__repr__(self))<br>
def __str__(self):<br>
return self._as_str()<br>
<br>
def _gen_format(self, indwidth, indstate):<br>
indst = indstate * ' '<br>
ind = (indstate + indwidth) * ' '<br>
yield ('\n' + indst + '{' if indstate else '{')<br>
for key, val in self.items():<br>
valstr = (str(val) if not isinstance(val, AttrDict)<br>
else val._as_str(indwidth, indstate + indwidth))<br>
yield '{ind}{key}: {valstr}'.format(ind=ind, key=key,<br>
valstr=valstr)<br>
yield indst + '}'<br>
<br>
def _as_str(self, indwidth=4, indstate=0):<br>
return '\n'.join(self._gen_format(indwidth, indstate))<br>
<br>
def _as_dict(self):<br>
return dict.copy(self)<br>
<br>
<br>
# Test code:<br>
if __name__ == '__main__':<br>
struct = AttrDict()<br>
struct.first = 1<br>
struct.second = 2.0<br>
struct.third = '3rd'<br>
struct.fourth = [4]<br>
print(struct)<br>
# output:<br>
# {<br>
# 'second': 2.0<br>
# 'fourth': [4]<br>
# 'third': '3rd'<br>
# 'first': 1<br>
# }<br>
<br>
del struct.fourth<br>
<br>
print(repr(struct))<br>
# output:<br>
# AttrDict({'second': 2.0, 'third': '3rd', 'first': 1})<br>
<br>
print(struct.first) # (static access)<br>
# output:<br>
# 1<br>
<br>
for x in ('first', 'second', 'third'):<br>
print(struct[x]) # (dynamic access)<br>
# output:<br>
# 1<br>
# 2.0<br>
# 3rd<br>
<br>
struct.sub = AttrDict(a=1, b=2, c=89)<br>
print(struct._as_dict())<br>
# output:<br>
# {'second': 2.0, 'sub': AttrDict({'a': 1, 'c': 89, 'b': 2}),\<br>
# 'third': '3rd', 'first': 1}<br>
<br>
print(struct._as_str(8))<br>
# output:<br>
# {<br>
# second: 2.0<br>
# sub:<br>
# {<br>
# a: 1<br>
# c: 89<br>
# b: 2<br>
# }<br>
# third: 3rd<br>
# first: 1<br>
# }<br>
<br>
<br>
What do you think about it?<br>
<br>
Cheers,<br>
*j<br><font color="#888888">
<br>
-- <br>
Jan Kaliszewski (zuo) <<a href="mailto:zuo@chopin.edu.pl" target="_blank">zuo@chopin.edu.pl</a>></font><div><div></div><div class="h5"><br>
-- <br>
<a href="http://mail.python.org/mailman/listinfo/python-list" target="_blank">http://mail.python.org/mailman/listinfo/python-list</a><br>
</div></div></blockquote></div><br>