Re: ANNOUNCE: Thesaurus - a recursive dictionary subclass usingattributes

Discussion in 'Python' started by Dave Cinege, Dec 12, 2012.

  1. Dave Cinege

    Dave Cinege Guest

    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
     
    Dave Cinege, Dec 12, 2012
    #1
    1. Advertising

  2. 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
    pass"
    1000000 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"
    1000000 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
     
    Steven D'Aprano, Dec 13, 2012
    #2
    1. Advertising

  3. On Thu, Dec 13, 2012 at 11:30 AM, Steven D'Aprano
    <> 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
    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
     
    Chris Angelico, Dec 13, 2012
    #3
  4. Dave Cinege

    Dave Cinege Guest

    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.
     
    Dave Cinege, Dec 13, 2012
    #4
  5. Dave Cinege

    Terry Reedy Guest

    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
     
    Terry Reedy, Dec 13, 2012
    #5
  6. Dave Cinege

    Dave Cinege Guest

    ANNOUNCE: Thesaurus - a recursive dictionary subclass usingattributes - v20121212

    Version 20121212
     
    Dave Cinege, Dec 13, 2012
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jason Friedman
    Replies:
    0
    Views:
    128
    Jason Friedman
    Dec 11, 2012
  2. Ian Kelly
    Replies:
    0
    Views:
    147
    Ian Kelly
    Dec 11, 2012
  3. Dave Cinege
    Replies:
    0
    Views:
    179
    Dave Cinege
    Dec 11, 2012
  4. Ian Kelly
    Replies:
    0
    Views:
    161
    Ian Kelly
    Dec 11, 2012
  5. Ian Kelly
    Replies:
    0
    Views:
    145
    Ian Kelly
    Dec 11, 2012
Loading...

Share This Page