having a function called after the constructor/__init__ is done

T

thomas.hansen

Hi all,

We've been breaking our heads over a good way of accomplishing an
"on_load" event in our multitouch GUI frameowork PyMT. We think we'd
like to trigger an "on_load" event after a class is fully instantiated
(or just a function call for simplicity, so you dont need to worry
about our specific system). This is so that if I make a subclass of
some widget, I dont have to overwrite the __init__ method (use super,
know the args, and pass them) everytime. Maybe I just want to do some
really basic stuff that doesn't really have anything to do with the
parent class.

Anyway. My first attempt was to simply put a call to self.on_load at
the end of the widget base class. This doesn't work though, because,
if I subclass it and do things after the call to super.__init__,
on_load will be called before the constructor finishes (when the top
most parent class __init__ finishes)

We've sort of managed to achieve this by using a decorator that
changes the __init__ function. but even this doesnt seem like the
best way to do this. a) I now have to decorate every constructor i
ever write. b) it seems impossible to make it so that it only happens
once after the object is actually instantiated (since i have a
decorator on all my constructors..each constructor in the inheritance
line will call on_load once)

Can I do something fancy with metaclasses here? I think I could kind
of do this by making all my classes use __new__, and then essentially
use __init__ as what i want on_load to be...but that just seems really
nasty and unpythonic. not to speak about the confusion it would cause
with people trying to figure out the library.

So any ideas on how to get a function called on an object just after
__init__ is done executing?
 
A

Armin Moradi

class MyClass(object):
def __init__(self, really_init=True):
self.a = 3
self.b = 4
# other initialization
if really_init: on_load()

def on_load(self):
print 'hello!'

class B(MyClass):
def __init__(self):
super(B, self).__init__(False)
self.c = 4
print "B initialized"
MyClass.on_load()

def on_load(self):
print 'hello!'


Would this work?

(posted it again to include the python-list in To:)
 
S

Steven D'Aprano

Hi all,

We've been breaking our heads over a good way of accomplishing an
"on_load" event in our multitouch GUI frameowork PyMT. We think we'd
like to trigger an "on_load" event after a class is fully instantiated ....
Can I do something fancy with metaclasses here?

class MetaLoad(type):
def __new__(cls, name, bases, dict):
obj = type.__new__(cls, name, bases, dict)
return obj
def __call__(cls, *args, **kwargs):
instance = super(MetaLoad, cls).__call__(*args, **kwargs)
instance.on_load()
return instance

class Parrot(object):
__metaclass__ = MetaLoad
def __init__(self, colour='blue'):
print "I'm a Norwegian %s." % colour
def on_load(self):
print "Loaded"
 
M

Michael Spencer

So any ideas on how to get a function called on an object just after
__init__ is done executing?

Yes, you *can* use metaclasses - you need to override the type.__call__ method,
which is what normally calls __new__ then __init__:
... def __call__(cls, *args, **kw):
... obj=type.__call__(cls, *args, **kw)
... obj.on_load()
... return obj
... ... __metaclass__ = MetaOnLoad
... def __init__(self):
... print "__init__ A"
... def on_load(self):
... print "on_load"
... ... def __init__(self):
... super(B,self).__init__()
... print "__init__ B"
... __init__ A
__init__ B
on_load ... def __init__(self):
... super(C,self).__init__()
... print "__init__ C"
... __init__ A
__init__ B
__init__ C
on_load ... def __new__(cls,*args, **kw):
... obj = object.__new__(cls, *args, **kw)
... print "__new__ D"
... return obj
... __new__ D
__init__ A
__init__ B
__init__ C
on_load
HTH
Michael
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top