Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #34595 > unrolled thread

ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

Started byDave Cinege <dave@cinege.com>
First post2012-12-10 22:48 -0500
Last post2012-12-13 00:15 +0000
Articles 10 — 5 participants

Back to article view | Back to comp.lang.python


Contents

  ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes Dave Cinege <dave@cinege.com> - 2012-12-10 22:48 -0500
    Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-12-11 08:12 +0000
      Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes Dave Cinege <dave@cinege.com> - 2012-12-11 16:08 -0500
        Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-12-12 06:34 +0000
        Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-12-12 06:34 +0000
          Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes Chris Angelico <rosuav@gmail.com> - 2012-12-12 17:44 +1100
          Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes "D'Arcy J.M. Cain" <darcy@druid.net> - 2012-12-12 05:25 -0500
    Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes Dave Cinege <dave@cinege.com> - 2012-12-12 13:13 -0500
    Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes Mark Lawrence <breamoreboy@yahoo.co.uk> - 2012-12-12 23:56 +0000
      Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-12-13 00:15 +0000

#34595 — ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

FromDave Cinege <dave@cinege.com>
Date2012-12-10 22:48 -0500
SubjectANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes
Message-ID<mailman.705.1355198321.29569.python-list@python.org>

[Multipart message — attachments visible in raw view] — view raw

Thesaurus: A different way to call a dictionary.

Thesaurus is a new a dictionary subclass which allows calling keys as
if they are class attributes and will search through nested objects
recursively when __getitem__ is called.

You will notice that the code is disgusting simple. However I have found that
this has completely changed the way I program in python. I've re-written some
exiting programs using Thesaurus, and often realized 15-30% code reduction.
Additionally I find the new code much easier to read.

If you find yourself programing with nested dictionaries often, fighting to 
generate output or command lines for external programs, or wish you had 
a dictionary that could act (sort of) like a class, Thesaurus may be for you.

[toc] | [next] | [standalone]


#34602

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2012-12-11 08:12 +0000
Message-ID<50c6eae2$0$21722$c3e8da3$76491128@news.astraweb.com>
In reply to#34595
On Mon, 10 Dec 2012 22:48:50 -0500, Dave Cinege wrote:

> Thesaurus: A different way to call a dictionary.

Is this intended as a ready-for-production class?


> Thesaurus is a new a dictionary subclass which allows calling keys as if
> they are class attributes and will search through nested objects
> recursively when __getitem__ is called.


If only that were true...

py> d = Thesaurus()
py> d['spam'] = {}
py> d['spam']['ham'] = 'cheese'  # key access works
py> d.spam.ham  # but attribute access doesn't
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'dict' object has no attribute 'ham'



> You will notice that the code is disgusting simple. However I have found
> that this has completely changed the way I program in python.

By making it less robust and more prone to errors?


py> d = Thesaurus()
py> d.copy = "some value"
py> assert d.copy == "some value"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError


Operations which silently fail or do the wrong thing are not a good 
thing. Scarily, this isn't even consistent:

py> "%(copy)s" % d
'some access'
py> d.copy
<built-in method copy of Thesaurus object at 0xb717a65c>



Some further comments about your code:


> class Thesaurus (dict):
> 	[...]
> 	def __getitem__(self, key):
> 		if '.' not in key:
> 			return dict.__getitem__(self, key)
> 		l = key.split('.')
> 		if isinstance(l[0], (dict, Thesaurus)):
> 			a = self.data

Testing for isinstance (dict, Thesaurus) is redundant, since Thesaurus is 
a subclass of dict.

More importantly, there are no circumstances where l[0] will be a dict. 
Since l is created by splitting a string, l[0] must be a string and this 
clause is dead code.

Which is good, because self.data is not defined anywhere, so if you ever 
did reach this branch, your code would fail.


> 		else:
> 			a = self
> 		for i in range(len(l)):		# Walk keys recursivly


This is usually better written as:

for subkey in l:
    # look up subkey
    # or if all else fails
    raise KeyError(subkey)


KeyError('spam.ham.cheese [1]') is misleading, since it implies to me 
that looking up spam.ham.cheese succeeded, and the failed lookup was on 
1. I would expect either of these:

KeyError('spam.ham')
KeyErroor('ham')

with a slight preference for the first.

Further issues with your code:

> 			try:
> 				a = a[l[i]]		# Attempt key
> 			except:


Bare excepts like this are not good. At best they are lazy and sloppy, 
good only for throw-away code. At worst, they are hide bugs. In this 
case, they can hide bugs:


py> class X(object):
...     @property
...     def test(self):
...             return 1/0  # oops a bug
... 
py> d = Thesaurus(a=X())
py> d.a.test  # Gives the correct exception for the error.
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in test
ZeroDivisionError: float division
py>
py> "%(a.test)s" % d  # Lies about the problem.
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 29, in __getitem__
KeyError: 'a.test [1]'



One more comment:


> # I like to create a master global object called 'g'.
> # No more 'global' statements for me.
> g = thes()

This is not a good thing. Encouraging the use of globals is a bad thing.



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#34647

FromDave Cinege <dave@cinege.com>
Date2012-12-11 16:08 -0500
Message-ID<mailman.743.1355260121.29569.python-list@python.org>
In reply to#34602
On Tuesday 11 December 2012 03:12:19 Steven D'Aprano wrote:

> Is this intended as a ready-for-production class?

For me, yes. In production code.

> py> d = Thesaurus()
> py> d['spam'] = {}

Maybe because spam is type dict instead of type thes???

>>> import thesaurus
>>> thes = thesaurus.Thesaurus
>>> t = thes()
>>> t.spam = thes()
>>> t.spam.ham = 'cheese'
>>> print t.spam.ham
>cheese
>>> print t['spam'].ham
>cheese
>>> print t['spam']['ham']
>cheese
>>> '%(spam.ham)s' % t
>'cheese'

Works for me!

Remainder of your post, not productive, not worth my time.

Dave

[toc] | [prev] | [next] | [standalone]


#34686

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2012-12-12 06:34 +0000
Message-ID<50c82577$0$21722$c3e8da3$76491128@news.astraweb.com>
In reply to#34647
On Tue, 11 Dec 2012 16:08:34 -0500, Dave Cinege wrote:

> On Tuesday 11 December 2012 03:12:19 Steven D'Aprano wrote:
> 
>> Is this intended as a ready-for-production class?
> 
> For me, yes. In production code.
> 
>> py> d = Thesaurus()
>> py> d['spam'] = {}
> 
> Maybe because spam is type dict instead of type thes???

Well duh. By the way, it's a dirty trick to cut out all context to try to 
make me seem like an idiot.

In context, you stated that Thesaurus "will search through nested objects
recursively when __getitem__ is called", but in fact that is not true. It 
does not do what you state it does.


> Remainder of your post, not productive, not worth my time.

Oh well I'm just hurt now. *sobs*

So, let's see now... I identified that your Thesaurus code:

* will fail silently;
* contains dead code that is never used;
* contains redundant code that is pointless;
* hides errors in the caller's code;

and you consider this "not productive, not worth my time". Code review 
with you must be *all* sorts of fun.



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#34687

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2012-12-12 06:34 +0000
Message-ID<50c82577$1$21722$c3e8da3$76491128@news.astraweb.com>
In reply to#34647
On Tue, 11 Dec 2012 16:08:34 -0500, Dave Cinege wrote:

> On Tuesday 11 December 2012 03:12:19 Steven D'Aprano wrote:
> 
>> Is this intended as a ready-for-production class?
> 
> For me, yes. In production code.
> 
>> py> d = Thesaurus()
>> py> d['spam'] = {}
> 
> Maybe because spam is type dict instead of type thes???

Well duh. By the way, it's a dirty trick to cut out all context to try to 
make me seem like an idiot.

In context, you stated that Thesaurus "will search through nested objects
recursively when __getitem__ is called", but in fact that is not true. It 
does not do what you state it does.


> Remainder of your post, not productive, not worth my time.

Oh well I'm just hurt now. *sobs*

So, let's see now... I identified that your Thesaurus code:

* will fail silently;
* contains dead code that is never used;
* contains redundant code that is pointless;
* hides errors in the caller's code;

and you consider this "not productive, not worth my time". Code review 
with you must be *all* sorts of fun.



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#34688

FromChris Angelico <rosuav@gmail.com>
Date2012-12-12 17:44 +1100
Message-ID<mailman.772.1355294667.29569.python-list@python.org>
In reply to#34687
On Wed, Dec 12, 2012 at 5:34 PM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> So, let's see now... I identified that your Thesaurus code:
>
> * will fail silently;
> * contains dead code that is never used;
> * contains redundant code that is pointless;
> * hides errors in the caller's code;
>
> and you consider this "not productive, not worth my time". Code review
> with you must be *all* sorts of fun.

He never asked for code review :)

ChrisA

[toc] | [prev] | [next] | [standalone]


#34690

From"D'Arcy J.M. Cain" <darcy@druid.net>
Date2012-12-12 05:25 -0500
Message-ID<mailman.774.1355308506.29569.python-list@python.org>
In reply to#34687
On Wed, 12 Dec 2012 17:44:24 +1100
Chris Angelico <rosuav@gmail.com> wrote:
> On Wed, Dec 12, 2012 at 5:34 PM, Steven D'Aprano
> <steve+comp.lang.python@pearwood.info> wrote:
> > and you consider this "not productive, not worth my time". Code
> > review with you must be *all* sorts of fun.
> 
> He never asked for code review :)

I think by posting it he sort of did.  He should probably grow a
thicker skin before he does so again though.

-- 
D'Arcy J.M. Cain <darcy@druid.net>         |  Democracy is three wolves
http://www.druid.net/darcy/                |  and a sheep voting on
+1 416 425 1212     (DoD#0082)    (eNTP)   |  what's for dinner.
IM: darcy@Vex.Net

[toc] | [prev] | [next] | [standalone]


#34716

FromDave Cinege <dave@cinege.com>
Date2012-12-12 13:13 -0500
Message-ID<mailman.792.1355336026.29569.python-list@python.org>
In reply to#34595
On Wednesday 12 December 2012 05:25:11 D'Arcy J.M. Cain wrote:

As a 16yr OSS vet I know that for every 1 person that that actually creates 
something there will always be 2000 people to bitch about it. My skin isn't 
thin, I just don't give a shit to listen to anyone one that doesn't get it.

The point to Thesaurus for those that want to pay attention:
The concept in these ~25 lines of code have changed the way I program Python
and reduced existing functionally identical code up to 30%...and I like the 
code better.

If that doesn't peak your interest, then move on...nothing here for you to 
see.

If you feel it needs to be expanded/corrected, do it and share it. If you can 
do it better, re-implement it. That's why I sent it to the mailing list.


> On Wed, 12 Dec 2012 17:44:24 +1100
> 
> Chris Angelico <rosuav@gmail.com> wrote:
> > On Wed, Dec 12, 2012 at 5:34 PM, Steven D'Aprano
> > 
> > <steve+comp.lang.python@pearwood.info> wrote:
> > > and you consider this "not productive, not worth my time". Code
> > > review with you must be *all* sorts of fun.
> > 
> > He never asked for code review :)
> 
> I think by posting it he sort of did.  He should probably grow a
> thicker skin before he does so again though.

[toc] | [prev] | [next] | [standalone]


#34736

FromMark Lawrence <breamoreboy@yahoo.co.uk>
Date2012-12-12 23:56 +0000
Message-ID<mailman.810.1355356595.29569.python-list@python.org>
In reply to#34595
On 12/12/2012 18:13, Dave Cinege wrote:
> On Wednesday 12 December 2012 05:25:11 D'Arcy J.M. Cain wrote:
>
> As a 16yr OSS vet I know that for every 1 person that that actually creates
> something there will always be 2000 people to bitch about it. My skin isn't
> thin, I just don't give a shit to listen to anyone one that doesn't get it.
>
> The point to Thesaurus for those that want to pay attention:
> The concept in these ~25 lines of code have changed the way I program Python
> and reduced existing functionally identical code up to 30%...and I like the
> code better.
>
> If that doesn't peak your interest, then move on...nothing here for you to
> see.

Please don't place responses like this.  The Python community prides 
itself on tolerance.  If you don't wish to follow that recommendation 
please go to an alternative site.

-- 
Cheers.

Mark Lawrence.

[toc] | [prev] | [next] | [standalone]


#34738

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2012-12-13 00:15 +0000
Message-ID<50c91e0c$0$29972$c3e8da3$5496439d@news.astraweb.com>
In reply to#34736
On Wed, 12 Dec 2012 23:56:24 +0000, Mark Lawrence wrote:

> Please don't place responses like this.  The Python community prides
> itself on tolerance.  If you don't wish to follow that recommendation
> please go to an alternative site.

Well, I must say, I think that you've just won an award for Most 
Cognitive Dissonance Exhibited In The Shortest Time. I'm not sure how you 
can yell at somebody that Google users should be dead in one post, and 
then nine minutes later say this.



-- 
Steven

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web