initializing mutable class attributes

Dan Perl dperl at rogers.com
Mon Aug 30 12:05:02 EDT 2004


Larry,

I don't think it is very different from what I suggested.  You still
implement an __init__ and you initialize the instance attributes there.

Thanks, though.  It's a nice trick and it's useful because you have a
default value that can be used also in other places in the code (like
restoring the default).  And it's probably a good use of pseudo-private
class attributes.

Dan

"Larry Bates" <lbates at swamisoft.com> wrote in message
news:29SdnfncSK8R3K7cRVn-sA at comcast.com...
> Dan,
>
> I too use class attributes to assign defaults, but do
> it like following:
>
> import copy
>
>     class Father:
>         _attr1default=None
>         _attr2default=[]
>
>         def __init__(self):
>             self.attr1=self._attr1default
>             # Get copy of attr2default
>             self.attr2=list(self._attr2default)
>
>          def foo(self, data):
>              self.attr1=data
>              self.attr2.append(data)
>
>
>      class Child (Father):
>          def __init__(self):
>              Father.__init__(self)
>              #
>              # At this point self.attr1 (instance)
>              # and self.attr2 (instance) hold their defaults
>              # while _attr1/_attr2default (class) still hold
>              # their default values for initialization of more
>              # class instances.
>              #
>
> HTH,
> Larry Bates
> Syscon, Inc.
>
>
> "Dan Perl" <dperl at rogers.com> wrote in message
> news:sHGYc.93306$pTn.42032 at news01.bloor.is.net.cable.rogers.com...
> > I will clarify something that was probably not clear enough in my
initial
> > posting.  I am interested in instance attributes, but I am using the
class
> > attributes to provide a default, "null", value for the instance
> attributes.
> > Yes, the instance attributes only mask the class ones, but a class
> attribute
> > and an instance attribute can be used like this:
> >     class WorksForMe:
> >         attr=None        # used just as a default value for the instance
> > attribute self.attr
> >         def foo(self):
> >             self.attr=SomethingUseful( )
> >         def bar(self):
> >             if self.attr:
> >                 useIt(self.attr)
> >             else:
> >                 ignoreIt(self.attr)
> > This makes it safe for an instance of WorksForMe to invoke bar( ) even
if
> it
> > never invoked foo( ).
> >
> > "Benjamin Niemann" <b.niemann at betternet.de> wrote in message
> > news:cgul4v$h1d$1 at online.de...
> > > That's the way it is supposed to work. Instance attributes have to be
> > > initialized via self.foo=..., usually in __init__() which in turn is
> > > *STRONGLY* advised to class its parents __init__() - or you create
> > > instance attributes 'on-the-fly' when they are used for the first time
> > > (useful technique for mixin classes without constructor). Class
> > > attributes are initialized once for the class and are shared between
> > > instances.
> >
> > You are confirming the code I suggested but you don't share my view that
> > such code is awkward.  I think I I was actually conservative calling it
> > awkward, I would rather call it unsafe.  If I were a third-party library
> > vendor, I would not be comfortable providing a mixin class that forces
> users
> > to either invoke the parent's __init__ in their constructors or to
> > initialize the instance attributes on-the-fly.  The latter would even be
> > against the principles of encapsulation, users should not need to know
> about
> > the parent's attributes, especially because they may change in future
> > releases.  Both ways of restricting the use of the mixin class are
unsafe
> > because they are easy to be ignored by users.  And it is not only the
> users'
> > fault if they do not follow the restrictions, it is also my fault to put
> > such restrictions in the first place.
> >
> > I think this points to a weakness in Python as an OO language.  I'm not
> > trying to bash it, but my understanding is that Python is still evolving
> in
> > that respect and I think that this should be improved in the future.
> Then,
> > on the other hand, maybe I'm the only one feeling this way and there's
not
> > going to be a change.
> >
> > > "self.attr1=data" in Father.foo() doesn't "override" the Father.attr1
> > > attribute you defined before. It creates an instance attribute that
> > > shadows Father.attr1!
> > > Both attribute assignments in Father are OK - if you treat them as
class
> > > attributes. They won't become instance attributes by hidden magic.
> > >
> > > Dan Perl wrote:
> > > > There is something with initializing mutable class attributes that I
> am
> > > > struggling with.  I'll use an example to explain:
> > > >     class Father:
> > > >         attr1=None   # this is OK
> > > >         attr2=[ ]        # this is wrong
> > > >         def foo(self, data):
> > > >             self.attr1=data
> > > >             self.attr2.append(data)
> > > > The initialization of attr1 is obviously OK, all instances of Father
> > > > redefine it in the method foo.  But the initialization of attr2 is
> wrong
> > > > because all the instances of Father end up sharing the same value.
> > Maybe
> > > > that is desired sometimes, but usually it is just a bug.
> > > >
> > > > So the only solution I see to this is to initialize attr2 in
__init__:
> > > >     class Father:
> > > >         attr1=None
> > > >         def __init__(self):
> > > >             self.attr2=[ ]
> > > >
> > > > This is already awkward because there is such a difference between
> attr1
> > and
> > > > attr2.  But moreover, I think this forces subclasses of Father to do
> > > > something like this:
> > > >     class Child (Father):
> > > >         def __init__(self):
> > > >             Father.__init__(self)
> > > >             self.attr3=[ ]
> > > >
> > > > I find this even more awkward because many people will forget to do
> it.
> > > > Clearly, this is then a more general issue with __init__, but I
think
> it
> > is
> > > > accentuated by the fact that you HAVE TO HAVE __init__ in order to
> > > > initialize attributes that are mutable.
> > > >
> > > > Is there something I don't know here and there is a better way to do
> > this in
> > > > Python?  I would like to get a better solution or otherwise start a
> > > > discussion.
> > >
> >
> >
>
>





More information about the Python-list mailing list