Re-executing the code object from a class 'declaration'

Carlos Ribeiro carribeiro at gmail.com
Wed Oct 6 22:10:16 CEST 2004


On Wed, 6 Oct 2004 21:28:40 +0200, Alex Martelli <aleaxit at yahoo.com> wrote:
> Carlos Ribeiro <carribeiro at gmail.com> wrote:
>    ...
> > > 1. You need to build an f = new.function(klass.my_code, globals()) in
> > >    your classmethod that now erroneously does the exec above quoted (you
> > >    could in fact do this in the metaclass, save the new function rather
> > >    than the code object -- get the right globals via inspect).
> >
> > That's the part that I was missing. It looks less 'hackish' than I had
> > expect. I was really afraid that I would need to manage bytecode-level
> > hacks myself. I am not as concerned about getting the right globals,
> > though -- it's good enough if I'm able to supply whatever globals I
> > need upon calling, I think (unless I'm _really_ missing something).
> 
> I don't think you're missing anything -- just DO consider that if you
> pass your own globals they'll be used to solve every name that's not
> local to the class body, e.g. a '__metaclass__ = metaname' assignment in
> classbody (of course, you can finesse this by calling the metaclass
> explicitly anyway;-).

I was missing the new.function() call -- I hadn't checked how could I
build a function out of a code block up to that point, and I was
afraid that I would need to dive deeply into Python internals. It's
not that bad.
 
> > > 2. you need to obtain the needed dict, that's just  d = f()  in your
> > >    method
> >
> > There is still a question, but I think I already know the anwswer :-)
> > If the class *has* a base class, it has to be passed as a parameter. I
> > assume that i can simply call it like this: d=f(bases); or instead,
> > that I can fill the argdefs in the new.function call. I'll try it
> > later.
> 
> Nope, f doesn't get the bases AT ALL; the bases (as a tuple) go in only
> when you call the metaclass.

Well. I was mistaken (and that's not be the first time). It goes like
this; I first checked the dis.dis() code:

 27          64 LOAD_CONST               4 ('MyClass')
             67 LOAD_NAME                7 (object)
             70 BUILD_TUPLE              1
             73 LOAD_CONST               5 (<code object MyClass at
0120A0A0, file "c:\work\help-on-c-l-py\re_exec_class.py", line 27>)
             76 MAKE_FUNCTION            0
             79 CALL_FUNCTION            0
             82 BUILD_CLASS         
             83 STORE_NAME               8 (MyClass)

... with that build_tuple there... besides that I knew I *can* access
the bases from within my class statement body:

class MyClass(MyBaseClass):
    bar = MyBaseClass.foo
 
... so I had suspected that the bases *were* passed to f(). But wait!
Actually, Python is building the stack for the BUILD_CLASS opcode.
Right?

> > > 3. you can now call your metaclass with the appropriate bases and name:
> > >        klas = self.__class__  # or cls if this is a classmethod;-)
> > >        return type(klas)(klas.__name__, klas.__bases__, d)
> > >
> > > voila, you're there.  This is all coded to minimize the need to have
> > > this method located in a specific class -- as I said I think you
> > > probably want to have this stuff in the metaclass (if you have a
> > > metaclass at all), but, whatever.
> >
> > Tehre are two reasons to do it in a metaclass: first, I tested it and
> > it works (of sorts), while for some reason it wont work for a
> > non-metaclasses enabled class. Also, because in this scenario there
> > are other things that I already need to check, and a metaclass does it
> > nicely.
> 
> OK, then, that's where you pass the bases in, not before.
> 
> > For now, I think I'll just be using the class-inside-a-def idiom. But
> 
> If it can give you all you need, that may be best.
> 
> > I'm still working around some design issues, and if the templating
> > mechanism gets in the final production code (it's only one of a few
> > competing designs), I'll surely try it again.
> 
> OK, keep us informed of developments, then!
> 
> 
> 
> 
> Alex
> --
> http://mail.python.org/mailman/listinfo/python-list
> 


-- 
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