Overriding a method at the instance level on a subclass of a builtin type
Jason Scheirer
jason.scheirer at gmail.com
Wed Dec 3 14:25:29 EST 2008
On Dec 2, 6:13 pm, Aaron Brady <castiro... at gmail.com> wrote:
> On Dec 2, 6:58 pm, "Zac Burns" <zac... at gmail.com> wrote:
>
>
>
> > Sorry for the long subject.
>
> > I'm trying to create a subclass dictionary that runs extra init code
> > on the first __getitem__ call. However, the performance of __getitem__
> > is quite important - so I'm trying in the subclassed __getitem__
> > method to first run some code and then patch in the original dict
> > method for the instance to avoid even the check to see if the init
> > code has been run. Various recipes using instancemethod and the like
> > have failed me.
>
> > Curiously if __slots__ is not specified no error occurs when setting
> > self.__getitem__ but the function is not overriden. If __slots__ is
> > ['__getitem__'] however it complains that __getitem__ is read only. I
> > do not understand that behavior.
>
> > --
> > Zachary Burns
> > (407)590-4814
> > Aim - Zac256FL
> > Production Engineer (Digital Overlord)
> > Zindagi Games
>
> That sounds like the State Pattern, from GoF. http://en.wikipedia.org/wiki/State_pattern
>
> I like the idea of 'renaming', not redefining, but reassigning methods
> at different points during an object's lifetime. I often wish I had
> more experience with it, and more docs talked about it.
>
> It's hard on memory usage, since each instance has its own function
> attribute, even if there's still only one instance of the function.
> Without it, the function attribute is just looked up on the class.
>
> Not thoroughly tested:
>
> >>> class A:
>
> ... def methA( self ):
> ... print 'methA'
> ... self.meth= self.methB
> ... meth= methA
> ... def methB( self ):
> ... print 'methB'
> ...>>> a= A()
> >>> a.meth()
> methA
> >>> a.meth()
>
> methB
The problem with using this this pattern in the way that you've
specified is that you have a potential memory leak/object lifetime
issue. Assigning a bound method of an instance (which itself holds a
reference to self) to another attribute in that same instance creates
a kind of circular dependency that I have discovered can trip up the
GC more often than not.
You can subclass it as easily:
class dictsubclass(dict):
def __getitem__(self, keyname):
if not hasattr(self, '_run_once'):
self.special_code_to_run_once()
self._run_once = True
return super(self, dict).__getitem__(keyname)
If that extra ~16 bytes associated with the subclass is really a
problem:
class dictsubclass(dict):
def __getitem__(self, keyname):
self.special_code_to_run_once()
self.__class__ = dict
return super(self, dict).__getitem__(keyname)
But I don't think that's a good idea at all.
More information about the Python-list
mailing list