Metaclasses?

Michael Hudson mwh21 at cam.ac.uk
Wed Apr 26 09:45:16 EDT 2000


Donald Beaudry <donb at init.com> writes:

> quinn at hedono.ugcs.caltech.edu (Quinn Dunkan) wrote,
> > Anyway, even if you could figure out the ambiguity problem, I don't
> > think metaclasses would help you, bytecodehacks might.
> 
> *If* bytecodehacks could help, metaclasses could be used to make
> calling them neat and clean.  The idea is that during class
> instantiation the metaclass would, using bytecodehacks, rewrite all of
> the class's methods.  This might confuse the poor guy who comes along
> and tries to derive a new class from one of these 'self less'.

What, like this? :-)

This has recieved light testing only, so be suitably careful.

deadline-on-Tuesday?-no-I-must-have-imagined-it-ly y'rs
Michael

from bytecodehacks.code_editor import Function
from bytecodehacks.ops import *
import types

def rewrite_method(meth,attrs):
    f = Function(meth)
    code = f.func_code
    cs = code.co_code

    code.co_varnames.insert(0,"self")
    code.co_names.insert(0,"self")
    
    i = 0
    while i < len(cs):
        op = cs[i]
        if op.__class__ in [LOAD_FAST,STORE_FAST,DELETE_FAST]:
            op.arg = op.arg + 1
        if  (op.has_name_or_local() and op.name in attrs
             and op.__class__ not in [LOAD_ATTR,STORE_ATTR]):
            if op.arg < code.co_argcount:
                raise ValueError, "parameter also instance member!"
            if op.__class__ in [LOAD_FAST, LOAD_NAME, LOAD_GLOBAL]:
                attrop = LOAD_ATTR
            else:
                attrop = STORE_ATTR
            cs[i:i+1] = [LOAD_FAST(0),attrop(op.name)]
            i = i + 2
        else:
            i = i + 1
    code.co_argcount = code.co_argcount + 1
    return f.make_function()

class SelflessClass:
    def __init__(self,name,bases,ns):
        self.__name__ = name
        self.__bases__ = bases
        self.__namespace__ = ns
        if ns.has_key('__attrs__'):
            attrs = ns['__attrs__']
            for k,v in ns.items():
                if type(v) is types.FunctionType:
                    ns[k] = rewrite_method(v,attrs)
    def __call__(self):
        return SelflessInstance(self)

class MetaMethodWrapper:
    def __init__(self, func, inst):
        self.func = func
        self.inst = inst
        self.__name__ = self.func.__name__

    def __call__(self, *args, **kw):
        return apply(self.func, (self.inst,) + args, kw)

class SelflessInstance:
    def __init__(self,klass):
        self.__klass__ = klass
        try:
            init = self.__klass__.__namespace__["__init__"]
        except:
            pass
        else:
            init(self)
    def __getattr__(self, name):
        try:
            value = self.__klass__.__namespace__[name]
            if type(value) is types.FunctionType:
                return MetaMethodWrapper(value,self)
            else:
                return value
        except KeyError:
            raise AttributeError, name

Selfless = SelflessClass("Selfless",(),{})

class MyClass(Selfless):
    __attrs__ = ["a"]
    def __init__():
        a = 1
    def get_a():
        return a
    def set_a(newa):
        a = newa

-- 
  If i don't understand lisp,  it would be wise to not bray about
  how lisp is stupid or otherwise criticize, because my stupidity 
  would be archived and open for all in the know to see.
                                               -- Xah, comp.lang.lisp



More information about the Python-list mailing list