Metaclass Question
Jay Parlar
jparlar at cogeco.ca
Wed Oct 6 18:46:47 EDT 2004
(Apologies in advance for the size of this message)
I decided to finally bite the bullet, and become part of the 1% of
people who understand metaclasses.
One of the examples of them I saw had to do with someone intercepting
the __init__ method of classes, and doing some fun stuff. I decided to
try something like that.
class MethodNameGetter(type):
'''
Any classes that use this metaclass can, at any time, reference
self.current_function, to get the name of the current function
being run
'''
'''
key: name of a class
value: { key: method reference, value: method name}
'''
nameReg = {}
def __init__(cls, name, bases, dict_):
super(MethodNameGetter, cls).__init__(name, bases, dict_)
cls_dict = cls.__dict__
funcs = [key for key, val in cls_dict.items() if type(val) ==
FunctionType]
print funcs
cls.nameReg[name] = {}
for func_name in funcs:
old_func = cls_dict[func_name]
code = old_func.func_code
defaults = old_func.func_defaults or ()
p_args = code.co_varnames[1:code.co_argcount]
p_kw = dict(zip(p_args[-len(defaults):], defaults))
def new_func(self, *args, **kw):
while True:
nameReg = self.__class__.nameReg
func_name =
nameReg[self.__class__.__name__][new_func]
setattr(self, "current_function", func_name)
t = eval("self._old_"+func_name)
print "t is", t
t(*args, **kw)
yield 0
cls.nameReg[name][new_func] = func_name
setattr(cls, "_old_" + func_name, old_func)
setattr(cls, func_name, lambda
*args,**kw:new_func(*args,**kw))
Essentially, what I'm trying to do here, is intercept all the methods
defined in some class, and make it so that if you call any methods in a
class, it will set self.current_function to the name of the method that
was just called. This would let me easily grab the name of the current
function being run, while being run.
My goal here isn't really the whole current_function thing, it's just
to learn metaclasses.
My class here is close, but the problem is with my 'def new_func'. For
some reason I assumed that "new instances" of it would get created for
each method being overridden, but they're not.
If I do this:
class A:
__metaclass__ = MethodNameGetter
def foo(self):
print "f"
print self.current_function
def bar(self):
print "b"
print self.current_function
t = A()
t.foo()
t.bar()
I should see:
> f
> foo
> b
> bar
Instead, I just see the stuff for foo(), two times.
Is there any way to make new instances of a function, short of a lambda?
Thanks in advance,
Jay P.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 2363 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-list/attachments/20041006/6bdd1c6b/attachment.bin>
More information about the Python-list
mailing list