Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2013-01-10 Thread Duncan Booth
Dave Cinege d...@cinege.com wrote:

 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
 relized 15-30% code reduction. Additionally I find the new code much
 easier to read. 

And here's the same code written without your class but maintaining as 
far as possible the same structure. I find my version far easier to read 
then your's with all your spurious 'g.' 'L.' prefixes.


-

#!python2.7
from textwrap import dedent

class Blob(object): pass

prog = Blob()
prog.VERSION = '1.0'# But isn't this so much cleaner?
prog.NAME = 'Thesaurus'

class TestClass:
no = 'Class'
way = 'this'

def main ():
tc = TestClass()
l = ['Some', 'objects']

# Here's how you should create output without a fight.
print dedent('''\
When programing python without {prog.NAME}, it is very
easy to access your {l[1]}.

{l[0]} people might say {prog.NAME} has no 
{tc.no}.''').format(prog=prog, l=l, tc=tc)

if hasattr(prog, 'VERSION'):
print 'But I challenge them to write code {tc.way} clean 
without it!'.format(**locals())

if __name__ == '__main__':
main()
-


-- 
Duncan Booth http://kupuguy.blogspot.com
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2013-01-10 Thread 88888 Dihedral
在 2013年1月10日星期四UTC+8下午7时34分23秒,Duncan Booth写道:
 Dave Cinege d...@cinege.com wrote:
 
 
 
  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
 
  relized 15-30% code reduction. Additionally I find the new code much
 
  easier to read. 
 
 
 
 And here's the same code written without your class but maintaining as 
 
 far as possible the same structure. I find my version far easier to read 
 
 then your's with all your spurious 'g.' 'L.' prefixes.
 
 
 
 
 
 -
 
 
 
 #!python2.7
 
 from textwrap import dedent
 
 
 
 class Blob(object): pass
 
 
 
 prog = Blob()
 
 prog.VERSION = '1.0'  # But isn't this so much cleaner?
 
 prog.NAME = 'Thesaurus'
 
 
 
 class TestClass:
 
   no = 'Class'
 
   way = 'this'
 
 
 
 def main ():
 
   tc = TestClass()
 
   l = ['Some', 'objects']
 
 
 
   # Here's how you should create output without a fight.
 
   print dedent('''\
 
   When programing python without {prog.NAME}, it is very
 
   easy to access your {l[1]}.
 
   
 
   {l[0]} people might say {prog.NAME} has no 
 {tc.no}.''').format(prog=prog, l=l, tc=tc)
 
 
 
   if hasattr(prog, 'VERSION'):
 
   print 'But I challenge them to write code {tc.way} clean 
 without it!'.format(**locals())
 
 
 
 if __name__ == '__main__':
 
   main()
 
 -
 
 
 
 
 
 -- 
 
 Duncan Booth http://kupuguy.blogspot.com

An object can accquire new properties and methods
in the run time without the limitations from 
the class definition of the object which belongs to.

This is a true OOP language.
-- 
http://mail.python.org/mailman/listinfo/python-list


ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2013-01-08 Thread Dave Cinege
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.
#!/usr/bin/env python

thesaurus.py		2012-09-13

Copyright (c) 2012 Dave Cinege
Licence: python, Copyright notice may not be altered.

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
recursivly 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 relized 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.

By example:
---
#!/usr/bin/env python

import thesaurus
thes = thesaurus.Thesaurus

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

g.prog = thes()
g['prog']['VERSION'] = '1.0'	# I can do this like a normal nested dictionary
g.prog.VERSION = '1.0'		# But isn't this so much cleaner?
g.prog.NAME = 'Thesaurus'

class TestClass:
	no = 'Class'
	way = 'this'

def main ():

	L = thes()		# Some local varibles

	L.tc = TestClass()	# We can also recurse to class attributes

	L.l = list()		# And recurse to indices too!
	L.l.append('Some')
	L.l.append('objects')
	
	g.L = L		# Easily make these locals global
	
	# Here's the real magic. Creating output without a fight.
	print '''
		When programing python using %(prog.NAME)s, it is very
		easy to access your %(L.l.1)s.
		
		%(L.l.0)s people might say %(prog.NAME)s has no %(L.tc.no)s.
	'''.replace('\t','')[1:-1] % g

	del g.L		# Clean locals up out of global space

	# If I was using a storage class, I must use hasattr() or an ugly eval.
	# But we can still use a str for the key name and 'in' like on any
	# regular dictionary.
	if 'VERSION' in g.prog:
		print 'But I challenge them to write code %(tc.way)s clean without it!' % L


if __name__ == '__main__':
	main()

---


__VERSION__ = 20120913

class Thesaurus (dict):
	def __getattr__(self, name):
		return self.__getitem__(name)
	def __setattr__(self, name, value):
		return dict.__setitem__(self, name, value)
	def __delattr__(self, name):
		return dict.__delitem__(self, name)
	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
		else:
			a = self
		for i in range(len(l)):		# Walk keys recursivly
			try:
a = a[l[i]]		# Attempt key
			except:
try:
	a = getattr(a, l[i])	# Attempt attr
except:
	try:
		a = a[int(l[i])]	# Attempt indice
	except:
		raise KeyError(key + ' [%s]' % i)
		return a
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2013-01-08 Thread Neal Becker
Did you intend to give anyone permission to use the code?  I see only a 
copyright notice, but no permissions.

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2013-01-08 Thread Ian Kelly
On Tue, Jan 8, 2013 at 12:16 PM, Neal Becker ndbeck...@gmail.com wrote:
 Did you intend to give anyone permission to use the code?  I see only a
 copyright notice, but no permissions.

It also says Licence: python, Copyright notice may not be altered.

Which suggests to me that the intent is that it be licensed under the
PSF License, although I wouldn't want to be the one testing that
inference in a courtroom.

Dave, this announcement looks identical to the one you posted a couple
months ago, and it also seems to include the earlier version of the
source.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-12 Thread D'Arcy J.M. Cain
On Wed, 12 Dec 2012 17:44:24 +1100
Chris Angelico ros...@gmail.com wrote:
 On Wed, Dec 12, 2012 at 5:34 PM, Steven D'Aprano
 steve+comp.lang.pyt...@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 da...@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: da...@vex.net
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-12 Thread Dave Cinege
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 ros...@gmail.com wrote:
  On Wed, Dec 12, 2012 at 5:34 PM, Steven D'Aprano
  
  steve+comp.lang.pyt...@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.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-12 Thread Dave Cinege
On Tuesday 11 December 2012 01:41:38 Ian Kelly wrote:

 I have a few critiques on the code.  First, you might want to use
 __getattribute__ instead of __getattr__.  Otherwise you'll end up

  File /home/dcinege/src/thesaurus/thesaurus.py, line 84, in 
__getattribute__
return self.__getitem__(name)
RuntimeError: maximum recursion depth exceeded while calling a Python object

This takes me into the same hell as when I was trying to implement this as a 
class. Someone else would have to take the time to do this. __getattr__ doing 
what I expect it to do, for what i do.

Dave


-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-12 Thread Ian Kelly
On Wed, Dec 12, 2012 at 12:20 PM, Dave Cinege d...@cinege.com wrote:
 On Tuesday 11 December 2012 01:41:38 Ian Kelly wrote:

 I have a few critiques on the code.  First, you might want to use
 __getattribute__ instead of __getattr__.  Otherwise you'll end up

   File /home/dcinege/src/thesaurus/thesaurus.py, line 84, in
 __getattribute__
 return self.__getitem__(name)
 RuntimeError: maximum recursion depth exceeded while calling a Python object

 This takes me into the same hell as when I was trying to implement this as a
 class. Someone else would have to take the time to do this. __getattr__ doing
 what I expect it to do, for what i do.

def __getattribute__(self, name):
if name.startswith('__') and name.endswith('__'):
return super(Thesaurus, self).__getattribute__(name)
return self.__getitem__(name)
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-12 Thread Dave Cinege
On Wednesday 12 December 2012 15:42:36 Ian Kelly wrote:

 def __getattribute__(self, name):
 if name.startswith('__') and name.endswith('__'):
 return super(Thesaurus, self).__getattribute__(name)
 return self.__getitem__(name)

Ian,

Tested, and works as you advertised.

Isn't super() depreciated? I've replaced it with this:
-return super(Thesaurus, self).__getattribute__(name)
+return dict.__getattribute__(self, name)

Aside from a more palatable result in the python shell for otherwise bad 
code...does this get me anything else? Is it really worth the performance hit 
of 2 string comparisons for every getattribute call?

I also just reviewed all your original comments again:

In general: The recursion code is nothing special to me and I finally settled 
on the nested try's as something simple that 'just works good for now'. 

I think the concept of what I'm doing here is the big idea.

Should the idea of implementing what Thesaurus does in mainline python ever 
happen, those 10 lines of code will likely spark a 3 month jihad about how to 
properly do in python which up until now hasn't been something you do in 
python.

To me for i in range(len(l)) seems like simpler, faster, tighter code for this 
now. It's duly noted that enumerate() is more python and I'm an old fart that 
still thinks too much in state machine. I've add except Exception per your 
advise.

What I'd really like to hear is that someone reading was curious enough to 
convert some existing code and their joy or displeasure with the experience.

Dave
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-12 Thread Ian Kelly
On Wed, Dec 12, 2012 at 3:20 PM, Dave Cinege d...@cinege.com wrote:
 On Wednesday 12 December 2012 15:42:36 Ian Kelly wrote:

 def __getattribute__(self, name):
 if name.startswith('__') and name.endswith('__'):
 return super(Thesaurus, self).__getattribute__(name)
 return self.__getitem__(name)

 Ian,

 Tested, and works as you advertised.

 Isn't super() depreciated? I've replaced it with this:
 -return super(Thesaurus, self).__getattribute__(name)
 +return dict.__getattribute__(self, name)

It's not deprecated.  Some people consider it harmful, and others
disagree.  I was once in the former camp but have shifted somewhat
toward the latter.

 Aside from a more palatable result in the python shell for otherwise bad
 code...does this get me anything else? Is it really worth the performance hit
 of 2 string comparisons for every getattribute call?

It could affect real code, not just interactive code.  Any time you
unthinkingly choose an attribute name that happens to be the name of a
dict method (e.g. 'items', which otherwise seems like a rather
innocent variable name), that's a potential bug.  Depending on how
that attribute is subsequently accessed, the bug might not even be
noticed immediately.

The performance hit compared to the __getattr__ version on my system
is about 1.3 microseconds per call, as measured by timeit, or around
40%.  For comparison, the performance hit of using the __getattr__
version versus just using a global variable is about 1.7 microseconds
per call, or around 4000%.  For my own use, I don't consider that
substantial enough to worry about, as I'm not in the business of
writing code that would be making hundreds of thousands of accesses
per second.

 Should the idea of implementing what Thesaurus does in mainline python ever
 happen, those 10 lines of code will likely spark a 3 month jihad about how to
 properly do in python which up until now hasn't been something you do in
 python.

The basic idea of proxying attribute access on a dict to key lookup is
pretty common, actually.  It likely won't ever make it into the
standard library because 1) there's no clear agreement on what it
should look like; 2) it's easy to roll your own; and 3) it looks too
much like JavaScript.  That last probably isn't valid; attribute
proxying is annoying and cumbersome when it automatically happens on
every single object in the language; it's much more manageable when
you have a single type like Thesaurus that you can use only in the
instances where you actually want it.

 To me for i in range(len(l)) seems like simpler, faster, tighter code for this
 now. It's duly noted that enumerate() is more python and I'm an old fart that
 still thinks too much in state machine. I've add except Exception per your
 advise.

Your intuition about what seems faster can lead you astray.  Using Python 2.7:

 timerD = timeit.Timer('for i in range(len(seq)): x = seq[i]', 'seq = 
 range(5)')
 timerE = timeit.Timer('for i, x in enumerate(seq): pass', 'seq = range(5)')
 min(timerD.repeat(3))
0.8711640725291545
 min(timerE.repeat(3))
0.7172601545726138

Of course, that's running each loop a million times, so the difference
here really is pretty negligible.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-12 Thread Mark Lawrence

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.

--
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-12 Thread Steven D'Aprano
On Wed, 12 Dec 2012 23:56:24 +, 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
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-12 Thread Steven D'Aprano
On Wed, 12 Dec 2012 17:20:53 -0500, Dave Cinege wrote:

 Isn't super() depreciated? 

Heavens no. super() is the recommended way to do inheritance, and the 
*only* way to correctly do multiple inheritance[1]. What makes you think 
that it has been deprecated?


[...]
 To me for i in range(len(l)) seems like simpler, faster, tighter code
 for this now. 

It's not. It is more complex, slower, less direct code. Python is not C, 
or Fortran, or whatever low-level language you cut your teeth on and get 
your intuitions from.

[steve@ando ~]$ python -m timeit -s L = list('abcdefghij') for i in 
range(len(L)):
c = L[i]
pass
100 loops, best of 3: 1.67 usec per loop
[steve@ando ~]$ python -m timeit -s L = list('abcdefghij') for i,c in 
enumerate(L):
pass
100 loops, best of 3: 1.39 usec per loop


That's only a small performance speedup, but the real advantages are:

* the version with enumerate is much more general: it works with 
  data structures where the length is expensive to calculate, lazy 
  data streams where the length is impossible to know up front, 
  and infinite data streams;

* the version with enumerate makes the intent more clear: since we
  care about looping over the items, we should iterate over the 
  items directly, not over their indices;

* it is more readable and maintainable: both loop variables (the
  index and the item) are defined in the same place, the start of 
  the for-loop, instead of one in the header and one in the body.



 What I'd really like to hear is that someone reading was curious enough
 to convert some existing code and their joy or displeasure with the
 experience.

I don't have any code with nested dicts where this would make a 
difference. If I had such code, I would be looking to redesign it so that 
I could avoided the nested dicts, not find a palliative. The Zen of 
Python is a useful guide to general design principles:

py import this
The Zen of Python, by Tim Peters

[...]
Flat is better than nested.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.

Your Thesaurus class violates too many of these principles for it to be 
of interest to me. Having spent a good hour or so playing around with it 
in the interactive interpreter, it is too hard for me to reason about 
what it is doing (especially since your description of what it does is 
actively misleading), and too hard to predict under what circumstances it 
will fail.

Short code is not necessarily simple code, and I find your class too 
magical and complicated to be interested in using it in production code 
as it stands now.




[1] Well, technically there's another way: one might reimplement the 
functionality of super() in your own code, and avoid using super() while 
having all the usual joys of reinventing the wheel.


-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-12 Thread Chris Angelico
On Thu, Dec 13, 2012 at 11:30 AM, Steven D'Aprano
steve+comp.lang.pyt...@pearwood.info wrote:
 On Wed, 12 Dec 2012 17:20:53 -0500, Dave Cinege wrote:
 To me for i in range(len(l)) seems like simpler, faster, tighter code
 for this now.

 * the version with enumerate makes the intent more clear: since we
   care about looping over the items, we should iterate over the
   items directly, not over their indices;

To add to this: Using enumerate gives the possibility (don't know if
any current interpreter takes advantage or not, but a future one
certainly could) that the enumerate() call could be optimized out.
Yes, it's theoretically possible that someone could redefine
enumerate, which would be broken by such an optimization. But all it'd
take is some kind of directive-based optimization and voila, safe
performance improvements.

Example code used:
 def foo(x):
for i,val in enumerate(x):
print(x[%d] = %s%(i,str(val)))

 def foo(x):
for i in range(len(x)):
val=x[i]
print(x[%d] = %s%(i,str(val)))

A simple look at dis.dis() for the above two functions disproves the
faster. Steven has already disproven the simpler and tighter.

(I would like, though, to see a key-providing iteration as a standard
feature. Looking at dis.dis() for the above examples and also at a
simple iteration over a dictionary's .items(), I'm seeing what looks
like a lot of effort to deal with the fact that iterators return a
stream of items, rather than a stream of keys and values. But it's
probably not worth changing now.)

ChrisA
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-12 Thread Dave Cinege
On Wednesday 12 December 2012 20:14:08 Chris Angelico wrote:

Ok enough already, I'll use the frigging thing!

Be happy I'm at least still not coding for python 1.5.

 To add to this: Using enumerate gives the possibility (don't know if
 any current interpreter takes advantage or not, but a future one
 certainly could) that the enumerate() call could be optimized out.
 Yes, it's theoretically possible that someone could redefine
 enumerate, which would be broken by such an optimization. But all it'd
 take is some kind of directive-based optimization and voila, safe
 performance improvements.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-12 Thread Terry Reedy

On 12/12/2012 7:30 PM, Steven D'Aprano wrote:

On Wed, 12 Dec 2012 17:20:53 -0500, Dave Cinege wrote:


Isn't super() depreciated?


Heavens no. super() is the recommended way to do inheritance, and the
*only* way to correctly do multiple inheritance[1].


Indeed. Rather than super() being deprecated, it was made easier to use 
in 3.x by being special cased during compilation. Notice the difference 
of signatures:


2.7: super(type[, object-or-type])
3.3: super([type[, object-or-type]])

The zero argument form only works inside a class definition, as the 
compiler fills in the necessary details to correctly retrieve the class 
being defined, as well as accessing the current instance for ordinary 
methods.



[1] Well, technically there's another way: one might reimplement the
functionality of super() in your own code, and avoid using super() while
having all the usual joys of reinventing the wheel.


This deeper integration means that it could not be completely 
reimplemented in Python ;-).


--
Terry Jan Reedy

--
http://mail.python.org/mailman/listinfo/python-list


ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes - v20121212

2012-12-12 Thread Dave Cinege
Version 20121212
#!/usr/bin/env python

thesaurus.py		2012-12-12

Copyright (c) 2012 Dave Cinege
Licence: PSF Licence, Copyright notice may not be altered.

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.

By example:
---
#!/usr/bin/env python

import thesaurus
thes = thesaurus.Thesaurus

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

g.prog = thes()
g['prog']['VERSION'] = '1.0'	# I can do this like a normal nested dictionary
g.prog.VERSION = '1.0'		# But isn't this so much cleaner?
g.prog.NAME = 'Thesaurus'

class TestClass:
	no = 'Class'
	way = 'this'

def main ():

	L = thes()		# Some local varibles

	L.tc = TestClass()	# We can also recurse to class attributes

	L.l = list()		# And recurse to indices too!
	L.l.append('Some')
	L.l.append('objects')
	
	g.L = L		# Easily make these locals global
	
	# Here's the real magic. Creating output without a fight.
	print '''
		When programing python using %(prog.NAME)s, it is very
		easy to access your %(L.l.1)s.
		
		%(L.l.0)s people might say %(prog.NAME)s has no %(L.tc.no)s.
	'''.replace('\t','')[1:-1] % g

	del g.L		# Clean locals up out of global space

	# If I was using a storage class, I must use hasattr() or an ugly eval.
	# But we can still use a str for the key name and 'in' like on any
	# regular dictionary.
	if 'VERSION' in g.prog:
		print 'But I challenge them to write code %(tc.way)s clean without it!' % L


if __name__ == '__main__':
	main()
---


__VERSION__ = 20121212

class Thesaurus (dict):
	def __getattribute__(self, name):
		if name.startswith('__') and name.endswith('__'):
			return dict.__getattribute__(self, name)
		return self.__getitem__(name)
	def __setattr__(self, name, value):
		return dict.__setitem__(self, name, value)
	def __delattr__(self, name):
		return dict.__delitem__(self, name)
	def __getitem__(self, key):
		if '.' not in key:
			return dict.__getitem__(self, key)
		a = self
		l = key.split('.')
		for i,v in enumerate(l):	# Walk keys recursivly
			try:
a = a[v]		# Attempt key
			except Exception:
try:
	a = getattr(a, v)	# Attempt attr
except Exception:
	try:
		a = a[int(v)]	# Attempt indice
	except Exception:
		raise KeyError('%(v)s (%(key)s[%(i)s])' % locals() )
		return a
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-12 Thread Dave Cinege
On Monday 10 December 2012 23:08:24 Jason Friedman wrote:

 2) Posting your code at ActiveState.com.

If someone wants to please do. I'm back to being completely overloaded with 
normal work now. The v20121212 release based on the last few days comments is 
as far as I will go with this now.

Dave
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-11 Thread Steven D'Aprano
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
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-11 Thread Jean-Michel Pichavant


- Original Message -
 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.
 
 --
 http://mail.python.org/mailman/listinfo/python-list
 

did you know you can write

class TestClass:
no = 'Class'
way = 'this'


tc = TestClass()

print Something you find clean, and I'm not sure why, this is way %(way)s and 
this is no %(no)s % vars(tc).


JM


-- IMPORTANT NOTICE: 

The contents of this email and any attachments are confidential and may also be 
privileged. If you are not the intended recipient, please notify the sender 
immediately and do not disclose the contents to any other person, use it for 
any purpose, or store or copy the information in any medium. Thank you.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-11 Thread Dave Cinege
On Tuesday 11 December 2012 01:41:38 Ian Kelly wrote:

 running into bugs like this:
  thes = Thesaurus()
  thes.update = 'now'
  thes.update
 
 built-in method update of Thesaurus object at 0x01DB30C8

I've noticed this but it's mostly pointless, as meaningful code does work.
(Also you stepped on the existing 'update()' dictionary method.)

 import thesaurus
 t = thesaurus.Thesaurus()
 t.s = 'now'
 t.s + ' this'
'now this'

Works perfect. However I'll take a look at __getattribute__  as from what you 
say it's more proper.

 Second, in __getitem__ you start a loop with for i in
 range(len(l)):, and then you use i as an index into l several times.
 It would be cleaner and more Pythonic to do for i, part in
 enumerate(l):, and then you can replace every occurrence of l[i]

My python is still 'old school' due to being stuck on old versions for in 
production embedded system python applications.

 It's not clear to me what the isinstance call here is meant to be
 testing for.

It's used to determine if it's the root instance of the recursive string 
because self.data, not self must be used to access that. Can you offer a better 
way?

 The prior statements require key to be a string.  If key
 is a string, then by construction l[0] is also a string.  So it seems
 to me that the isinstance check here will always be False.

OK, try and remove it and then get back to me. :-)

 In any case, the key splitting here seems to be done primarily to
 support the use of formatting placeholders like %(L.l.1)s in the
 examples.  I want to point out that this use case is already well
 supported (I might even say better supported since it cleanly
 distinguishes index elements from attributes with syntax) by the

Thesaurus recursion works with modules like Template, in addition to allowing 
easy hierarchical organization of (global) data. It's not about string 
formatting. It's about organizing data and recursive retrieval of that data.

 Lastly, you have several bare except clauses in the code.  Bare

Not going to get into religion. There is no 'correct' way to do this code at 
all because it's not established normal python. I left it simple and it suits 
my needs. I've converted several production commercial utilities and 
applications to use Thesaurus, and have seen nothing but benefit.

If anyone needs more to this, have at it, I'm busy

Dave

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-11 Thread Dave Cinege
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
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-11 Thread Ian Kelly
On Tue, Dec 11, 2012 at 1:57 PM, Dave Cinege d...@linkscape.net wrote:
 On Tuesday 11 December 2012 01:41:38 Ian Kelly wrote:
 Second, in __getitem__ you start a loop with for i in
 range(len(l)):, and then you use i as an index into l several times.
 It would be cleaner and more Pythonic to do for i, part in
 enumerate(l):, and then you can replace every occurrence of l[i]

 My python is still 'old school' due to being stuck on old versions for in
 production embedded system python applications.

Just out of curiosity, how old are we talking?  enumerate was added in
Python 2.3, which is nearly 10 years old.  Prior to 2.2 I don't think
it was even possible to subclass dict, which would make your Thesaurus
implementation unusable, so are these systems running Python 2.2?

 It's not clear to me what the isinstance call here is meant to be
 testing for.

 It's used to determine if it's the root instance of the recursive string
 because self.data, not self must be used to access that. Can you offer a 
 better
 way?

 The prior statements require key to be a string.  If key
 is a string, then by construction l[0] is also a string.  So it seems
 to me that the isinstance check here will always be False.

 OK, try and remove it and then get back to me. :-)

Okay.  I replaced this code:

if isinstance(l[0], (dict, Thesaurus)):
a = self.data
else:
a = self

with:

a = self

and then I ran the examples, and the output was unchanged.  As Steven
pointed out, I don't see how that first branch could succeed anyway,
since self.data is never defined.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-11 Thread Ian Kelly
On Tue, Dec 11, 2012 at 2:53 PM, Ian Kelly ian.g.ke...@gmail.com wrote:
 and then I ran the examples, and the output was unchanged.  As Steven
 pointed out, I don't see how that first branch could succeed anyway,
 since self.data is never defined.

It occurs to me that the UserDict class does have a data attribute.
Perhaps there was another version of Thesaurus that inherited from
UserDict instead of dict, and so the access to .data is a holdover
from legacy code?
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-11 Thread Dave Cinege
On Tuesday 11 December 2012 16:53:12 Ian Kelly wrote:

 Just out of curiosity, how old are we talking?  enumerate was added in
 Python 2.3, which is nearly 10 years old.  Prior to 2.2 I don't think
 it was even possible to subclass dict, which would make your Thesaurus
 implementation unusable, so are these systems running Python 2.2?

I'm finally beyond 2.2 and getting rid of 2.4 soon. Just started using 2.6 5 
months ago.

Thesaurus initially came about from me doing this:
class Global:
pass
g = Global()

As a way to organize/consolidate global vars and eliminate the global 
statement.

After a brain fart one day I expanded this to some simple recursion and felt I 
was onto something as my entire life changed with how easy it now was to build 
output strings.

As you noted it was not possible to subclass dict, so I first tried with a 
class, and you run into recursion hell with __setatrib__ to which i think 
there is no fix.

I then made a UserDict version. Then when I moved mostly to 2.6 I could do a 
proper dict subclass. 

So I believe you're actually correct here 

 if isinstance(l[0], (dict, Thesaurus)):
a = self.data

Looks like an artifact from my UserDict version and was needed.  :-(

class UserDict:
def __init__(self, dict=None, **kwargs):
self.data = {}

Thanks for this. You'll see from the version number I wrote this 3 months ago 
so it's not 100% fresh in my mind. I'm releasing it now because a python coder 
I contracted to pick up some slack for me saw this and went ape at how much he 
liked it...and that prompted me to finally get it out into the wild.

As for in depth discussion and enhancement to this, I lack the time.

Dave
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-11 Thread Cameron Simpson
On 11Dec2012 15:57, Dave Cinege d...@linkscape.net wrote:
| On Tuesday 11 December 2012 01:41:38 Ian Kelly wrote:
|  running into bugs like this:
|   thes = Thesaurus()
|   thes.update = 'now'
|   thes.update
|  
|  built-in method update of Thesaurus object at 0x01DB30C8
| 
| I've noticed this but it's mostly pointless, as meaningful code does work.
| (Also you stepped on the existing 'update()' dictionary method.)

I think that was a deliberate choice of name by Ian.

I've got a class like Thesaurus that subclasses dict and maps attributes
to dictionary elements (with a few special purpose tweaks I could go into
if anyone cares). I made a deliberate decision to only map UPPERCASE
attributes to dict keys to avoid exactly the kind of conflict above,
because:

  thes.update = 'now'

must either trash the dict.update method _or_ fail to present .update as
'now'. Both have their downsides. So at the cost of shoutier but still
effective code I accepted only .UPPERCASE attribute names as mapping to
keys.

This compromise also makes subclassing much easier, because the
subclasser is free to use conventional lowercase attribute names.

Cheers,
-- 
Cameron Simpson c...@zip.com.au

Thousands at his bidding speed,
And post o'er land and ocean without rest   - Milton
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-11 Thread Dave Cinege
On Tuesday 11 December 2012 17:39:12 Dave Cinege wrote:

My memory is getting jogged more why did some things:

raise KeyError(key + ' [%s]' % i)

I did this to specificly give you the indice that failed recursion but provide 
the entire key name as it was provided to __getitem__

So if:
g.cfg.host.cpu
fails recursion on 'host' you will see:  g.cfg.host.cpu [2]
I know my code sent g.cfg.host.cpu. I know host failed. if It was 
g.cfg.host.host, I'd know which host failed.

Makes sense to me. Works for me. Sure there are other ways to do it.

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-11 Thread Mitya Sirenef

On 12/11/2012 05:39 PM, Dave Cinege wrote:

On Tuesday 11 December 2012  16:53:12 Ian Kelly wrote:


 Just out of curiosity, how old are we talking? enumerate was added in
 Python 2.3, which is nearly 10 years old. Prior to 2.2 I don't think
 it was even possible to subclass dict, which would make your Thesaurus
 implementation unusable, so are these systems running Python 2.2?

 I'm finally beyond 2.2 and getting rid of 2.4 soon. Just started 
using 2.6 5

 months ago.

 Thesaurus initially came about from me doing this:
 class Global:
 pass
 g = Global()

 As a way to organize/consolidate global vars and eliminate the global
 statement.


I think that's the key issue here. I find that when code is well
structured, you pretty much never have a need for global statements,
anyway.

By the way, the Thesaurus class reminds me of using the old recipe
called 'Bunch':

http://code.activestate.com/recipes/52308-the-simple-but-handy-collector-of-a-bunch-of-named/

like this:

b = Bunch(x=1) b.stuff = Bunch(y=2)

b.stuff.y 2

I've also seen an answer on StackOverflow that uses automatic recursive
'Bunching':

http://stackoverflow.com/questions/1123000/does-python-have-anonymous-classes

I've seen another variation of recursive bunching, I think it was by
Alex Martelli on StackOverflow, but I can't find it now, I believe it
used defaultdict as part of it..

This approach can be handy sometimes but has drawbacks, as others have
pointed out.

I think the issue is that it's not a solution for avoiding globals,
which is not a problem in need of solution, but this can be a quick and
dirty way to organize a few levels of dicts/Bunches and usually people
come up with a custom variation on these recipes that suit their
program.


--
Lark's Tongue Guide to Python: http://lightbird.net/larks/

--
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-11 Thread Mitya Sirenef

On 12/11/2012 07:53 PM, Mitya Sirenef wrote:

By the way, the Thesaurus class reminds me of using the old recipe
called 'Bunch':

http://code.activestate.com/recipes/52308-the-simple-but-handy-collector-of-a-bunch-of-named/ 



like this:

b = Bunch(x=1) b.stuff = Bunch(y=2)

b.stuff.y 2 


Sorry, this was meant to be:

b = Bunch(x=1)
b.stuff = Bunch(y=2)

b.stuff.y
 2

--
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-11 Thread Steven D'Aprano
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
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-11 Thread Steven D'Aprano
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
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-11 Thread Chris Angelico
On Wed, Dec 12, 2012 at 5:34 PM, Steven D'Aprano
steve+comp.lang.pyt...@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
-- 
http://mail.python.org/mailman/listinfo/python-list


ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-10 Thread Dave Cinege
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.
#!/usr/bin/env python

thesaurus.py		2012-09-13

Copyright (c) 2012 Dave Cinege
Licence: python, Copyright notice may not be altered.

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
recursivly 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 relized 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.

By example:
---
#!/usr/bin/env python

import thesaurus
thes = thesaurus.Thesaurus

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

g.prog = thes()
g['prog']['VERSION'] = '1.0'	# I can do this like a normal nested dictionary
g.prog.VERSION = '1.0'		# But isn't this so much cleaner?
g.prog.NAME = 'Thesaurus'

class TestClass:
	no = 'Class'
	way = 'this'

def main ():

	L = thes()		# Some local varibles

	L.tc = TestClass()	# We can also recurse to class attributes

	L.l = list()		# And recurse to indices too!
	L.l.append('Some')
	L.l.append('objects')
	
	g.L = L		# Easily make these locals global
	
	# Here's the real magic. Creating output without a fight.
	print '''
		When programing python using %(prog.NAME)s, it is very
		easy to access your %(L.l.1)s.
		
		%(L.l.0)s people might say %(prog.NAME)s has no %(L.tc.no)s.
	'''.replace('\t','')[1:-1] % g

	del g.L		# Clean locals up out of global space

	# If I was using a storage class, I must use hasattr() or an ugly eval.
	# But we can still use a str for the key name and 'in' like on any
	# regular dictionary.
	if 'VERSION' in g.prog:
		print 'But I challenge them to write code %(tc.way)s clean without it!' % L


if __name__ == '__main__':
	main()

---


__VERSION__ = 20120913

class Thesaurus (dict):
	def __getattr__(self, name):
		return self.__getitem__(name)
	def __setattr__(self, name, value):
		return dict.__setitem__(self, name, value)
	def __delattr__(self, name):
		return dict.__delitem__(self, name)
	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
		else:
			a = self
		for i in range(len(l)):		# Walk keys recursivly
			try:
a = a[l[i]]		# Attempt key
			except:
try:
	a = getattr(a, l[i])	# Attempt attr
except:
	try:
		a = a[int(l[i])]	# Attempt indice
	except:
		raise KeyError(key + ' [%s]' % i)
		return a
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-10 Thread Jason Friedman
 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.

Good stuff.  You might consider:
1) Licensing under an OSI-approved license
(http://opensource.org/licenses/index.html).
2) Posting your code at ActiveState.com.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass using attributes

2012-12-10 Thread Ian Kelly
On Mon, Dec 10, 2012 at 8:48 PM, Dave Cinege d...@cinege.com wrote:
 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.

I have a few critiques on the code.  First, you might want to use
__getattribute__ instead of __getattr__.  Otherwise you'll end up
running into bugs like this:

 thes = Thesaurus()
 thes.update = 'now'
 thes.update
built-in method update of Thesaurus object at 0x01DB30C8

Hey, where'd my data go?  The answer is that it is in the Thesaurus:

 thes['update']
42

But it's not visible as an attribute because it is shadowed by the
dict methods.  Using __getattribute__ instead of __getattr__ would
mean that those non-special methods simply wouldn't be visible at all.

Second, in __getitem__ you start a loop with for i in
range(len(l)):, and then you use i as an index into l several times.
It would be cleaner and more Pythonic to do for i, part in
enumerate(l):, and then you can replace every occurrence of l[i]
with part (or whatever you want to call that variable).

Third, also in __getitem__ you have this code:


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


It's not clear to me what the isinstance call here is meant to be
testing for.  The prior statements require key to be a string.  If key
is a string, then by construction l[0] is also a string.  So it seems
to me that the isinstance check here will always be False.

In any case, the key splitting here seems to be done primarily to
support the use of formatting placeholders like %(L.l.1)s in the
examples.  I want to point out that this use case is already well
supported (I might even say better supported since it cleanly
distinguishes index elements from attributes with syntax) by the
str.format style of string formatting:

 L = {'l': ['zero', 'one']}
 There should be {L[l][1]}-- and preferably only {L[l][1]} --obvious way to 
 do it..format(L=L)
'There should be one-- and preferably only one --obvious way to do it.'

Lastly, you have several bare except clauses in the code.  Bare
excepts are almost always incorrect.  I appreciate that it's not easy
to predict exactly what exceptions might turn up here (although I
posit that for all of these, subsets of (TypeError, KeyError,
AttributeError, IndexError) are sufficient), but at the very minimum
you should specify except Exception, so that you're not
inadvertently catching things like SystemExit and KeyboardInterrupt.

Cheers and hope this is helpful,
Ian
-- 
http://mail.python.org/mailman/listinfo/python-list