class constructors: class vs. instance defaults

Michael Hoffman m.h.3.9.1.without.dots.at.cam.ac.uk at example.com
Wed Oct 6 18:51:43 EDT 2004


Erik Johnson <ej <at> wellkeeper wrote:

> You might be surprised to find out that all the Bar objects end up
> sharing the same foo_d dictionary.

I wasn't <wink> but I can see why one might not expect this. There was a 
thread on this phenomenon this very week...

> I struggled with that for a
> while and eventually reasoned that the {} in the argument list to my
> constructor is executed at the time of class definition, and is essentially
> a reference to an instantiated dictionary object and therefor there is a
> little empty dictionary sitting in memory somewhere prior to me ever
> instantiating a Bar object.  New Bar objects constructed without providing
> their own foo_d end up sharing that one.  I think this makes sense enough,
> now  (if I'm missing something, speak up).

That's exactly right.

>     So, one work-around is to do this:
> 
> #=======================================================================
> class Bar:
> 
>     def __init__(self, foo_d=None)
>         if foo_d:
>             self.foo_d = foo_d
>         else:
>             self.foo_d = {}

To be honest that is almost exactly what I would do. Except that I would 
use "if foo_d is not None" because the truth value of an empty container 
(such as {}) is False. So if someone specified an empty dict subclass or 
a list as the foo_d, you would end up creating a new empty dict instead 
for self.foo_d.

Maybe that is a little far-fetched, but you seem to want to start with 
good habits (which is very commendable), and using "if x is not None" 
when you want to test whether it is None or not is a good idea. :)

 > Is there a better way to do this sort of thing, or is that
> perfectly reasonable code?

Looks reasonable enough to me.
-- 
Michael Hoffman



More information about the Python-list mailing list