Why is __root checked for in OrderedDict?

2011-04-07 Thread andrew cooke
If you look at the code in 
http://hg.python.org/cpython/file/6adbf5f3dafb/Lib/collections/__init__.py#l49 
the attribute __root is checked for, and only created if missing.  Why?

I ask because, from what I understand, the __init__ method will only be called 
when the object is first being created, so __root will always be missing.

My only guess is that this allows subclasses to do strange things without 
breaking the code (and if so, is a nice defensive coding pattern).  But I am 
worried I am missing something.

Thanks,
Andrew
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Why is __root checked for in OrderedDict?

2011-04-07 Thread Raymond Hettinger
On Apr 7, 4:13 am, andrew cooke and...@acooke.org wrote:
 If you look at the code 
 inhttp://hg.python.org/cpython/file/6adbf5f3dafb/Lib/collections/__init...the 
 attribute __root is checked for, and only created if missing.  Why?

 I ask because, from what I understand, the __init__ method will only be 
 called when the object is first being created, so __root will always be 
 missing.

First of all, three cheers for reading the source code!

A user can call __init__() even after the OrderedDict instance has
already been created.  If so, the __root attribute will already exist
and the whole operation becomes equivalent to an update().

You can see the same behavior with regular dictionaries:

 d = dict(a=1, b=2)
 d.__init__(b=4, c=5)
 d
{'a': 1, 'c': 5, 'b': 4}


Raymond

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


Re: Why is __root checked for in OrderedDict?

2011-04-07 Thread andrew cooke
Is that normal?  I mean, OK, it's possible (and yes I forgot it could be called 
directly), but is there any usual reason to do so?

I guess what I'm asking is: if I'm writing library code should I be this 
careful?   (I've written quite a lot of Python code without this ever biting 
me, but maybe I'm just lazy).  For example, would you consider it a bug if 
someone complained that calling __init__() resulted in unexpected behaviour?

Thanks,
Andrew
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Why is __root checked for in OrderedDict?

2011-04-07 Thread Raymond Hettinger
On Apr 7, 2:40 pm, andrew cooke and...@acooke.org wrote:
 Is that normal?  I mean, OK, it's possible (and yes I forgot it could be 
 called directly), but is there any usual reason to do so?

It's common for subclasses to call their parent's __init__ method, so
that should emulate dict as nearly as possible to help avoid
surprises.

For the most part, client code won't use __init__ directly because
update() already provides equivalent functionality (but with a better
name).

For list.__init__(), the behavior is different.  It clears the list,
so someone may be using an __init__ call when it isn't practical to
use the syntactic equivalents del a[:] or a[:] = [].

Outside those cases, I don't it is normal, but who knows what future
programmers will need to do?


 I guess what I'm asking is: if I'm writing library code should I be this 
 careful?

For the standard library, it pays to really think out the corner cases
because you never know what people are going to rely on.  The Liskov
substitution principle asks us to make OrderedDict behave as much like
dict as possible (so that OD's can be used a drop-in substitute when
needed).

Also subclassers tend to stress the API in ways that wouldn't be
common for the base class.

For standard library code, I think all the little things matter:
* int(), bool(), list() etc all return a zero
  value when called with no arguments
* the ordered dict code internally calls __update()
  instead of update() so that a subclass can override
  update() without breaking the constructor
* eval(repr(obj)) should round-trip whereever possible
* containers should behave reasonable well even if someone
  makes the container reference itself:  a=[]; a.append(a)
* classes should try to be pickable, copyable, and deepcopyable, etc
 ...

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