Re-executing the code object from a class 'declaration'
Carlos Ribeiro
carribeiro at gmail.com
Wed Oct 6 07:25:06 EDT 2004
In respectful consideration to Alex's opposition to the misuse of the
word 'declaration', here is a repost with the suggested changes:
---
As part of a pet project of mine, I needed to find a way to re-execute
a class statement. The reason behind it was simple: the class
statement in question had some external dependencies that could
potentially change during the lifetime of the program. I needed to be
able to execute the class statement block again to produce new
classes (in opposition to new instances, which would not solve my
problem)[1].
I solved the problem using inspect to find the current code object
*inside* the class statement, and stored it in an attribute of the
class itself. Then, a method of the class can be used to re-create it.
A metaclass-enabled version is shown below:
class Meta(type):
def __new__(klass, name, bases, dct):
dct['my_code'] = inspect.currentframe(1).f_code
return type(name, bases, dct)
class MyClass:
__metaclass__ = Meta
creation_time = time.ctime()
print "I'm inside my class definition!"
def re_execute(klass):
exec klass.my_code
return MyClass
re_execute = classmethod(re_execute)
Testing:
>>> class MyClass:
...
I'm inside my class definition!
>>> id(MyClass)
8737376
>>> MyClass.creation_time
'Tue Oct 05 21:50:25 2004'
>>> NewClass = MyClass.re_execute()
I'm inside my class definition!
>>> id(NewClass)
8736912
>>> NewClass.creation_time
'Tue Oct 05 21:51:20 2004'
Implementation notes:
1) The exec statement actually binds the name to the same original
name, but in the current local scope. That's why it does a 'return
MyClass' in the re_execute() method. The MyClass symbol refers to the
local symbol with this name that was just re-created by the exec
method.
2) If you call the exec from the same scope where the class was
originally created, then it is automatically bound to the same name:
>>> id(MyClass)
8737376
>>> MyClass.creation_time
'Tue Oct 05 21:50:25 2004'
>>> exec MyClass.my_code
I'm inside my class definition!
>>> id(MyClass)
8744512
>>> MyClass.creation_time
'Tue Oct 05 21:56:53 2004'
3) I thought that the same technique could be made to work without a
metaclass, but I couldn't make it work. I haven't invested much time
to understand why -- it just works as implemented above. (It seems
that it does not bind correctly to the original name as it does if you
use the metaclass)
----
[1] Think about it as a templating mechanism, similar to the C++ one,
but for Python; this mechanism generates new classes that can be
instantiated as many times as needed. It's not the same thing as to
customize a instance during its initialization.
--
Carlos Ribeiro
Consultoria em Projetos
blog: http://rascunhosrotos.blogspot.com
blog: http://pythonnotes.blogspot.com
mail: carribeiro at gmail.com
mail: carribeiro at yahoo.com
More information about the Python-list
mailing list