Let\'s say you have an object that was instantiated from a class inside a module. Now, you reload that module. The next thing you\'d like to do is make that reload affect that c
You have to get the new class from the fresh module and assign it back to the instance.
If you could trigger this operation anytime you use an instance with this mixin:
import sys
class ObjDebug(object):
def __getattribute__(self,k):
ga=object.__getattribute__
sa=object.__setattr__
cls=ga(self,'__class__')
modname=cls.__module__
mod=__import__(modname)
del sys.modules[modname]
reload(mod)
sa(self,'__class__',getattr(mod,cls.__name__))
return ga(self,k)
The following code does what you want, but please don't use it (at least not until you're very sure you're doing the right thing), I'm posting it for explanation purposes only.
mymodule.py:
class ClassChange():
@classmethod
def run(cls,instance):
print 'one',id(instance)
myexperiment.py:
import mymodule
myObject = mymodule.ClassChange()
mymodule.ClassChange.run(myObject)
# change mymodule.py here
reload(mymodule)
mymodule.ClassChange.run(myObject)
When in your code you instanciate myObject
, you get an instance of ClassChange
. This instance has an instance method called run
. The object keeps this instance method (for the reason explained by nosklo) even when reloading, because reloading only reloads the class ClassChange
.
In my code above, run
is a class method. Class methods are always bound to and operate on the class, not the instance (which is why their first argument is usually called cls
, not self
). Wenn ClassChange
is reloaded, so is this class method.
You can see that I also pass the instance as an argument to work with the correct (same) instance of ClassChange. You can see that because the same object id is printed in both cases.
You have to make a new object. There's no way to magically update the existing objects.
Read the reload builtin documentation - it is very clear. Here's the last paragraph:
If a module instantiates instances of a class, reloading the module that defines the class does not affect the method definitions of the instances — they continue to use the old class definition. The same is true for derived classes.
There are other caveats in the documentation, so you really should read it, and consider alternatives. Maybe you want to start a new question with why you want to use reload
and ask for other ways of achieving the same thing.
My approach to this is the following:
Advantages to this approach are:
You can read about the technique (and its limitations) here: http://luke-campagnola.blogspot.com/2010/12/easy-automated-reloading-in-python.html
And you can download the code here: http://luke.campagnola.me/code/downloads/reload.py
I'm not sure if this is the best way to do it, or meshes with what you want to do... but this may work for you. If you want to change the behavior of a method, for all objects of a certain type... just use a function variable. For example:
def default_behavior(the_object):
print "one"
def some_other_behavior(the_object):
print "two"
class Foo(object):
# Class variable: a function that has the behavior
# (Takes an instance of a Foo as argument)
behavior = default_behavior
def __init__(self):
print "Foo initialized"
def method_that_changes_behavior(self):
Foo.behavior(self)
if __name__ == "__main__":
foo = Foo()
foo.method_that_changes_behavior() # prints "one"
Foo.behavior = some_other_behavior
foo.method_that_changes_behavior() # prints "two"
# OUTPUT
# Foo initialized
# one
# two
You can now have a class that is responsible for reloading modules, and after reloading, setting Foo.behavior
to something new. I tried out this code. It works fine :-).
Does this work for you?
There are tricks to make what you want possible.
Someone already mentioned that you can have a class that keeps a list of its instances, and then changing the class of each instance to the new one upon reload.
However, that is not efficient. A better method is to change the old class so that it is the same as the new class.