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