Created
September 14, 2010 01:27
-
-
Save mattvonrocketstein/578382 to your computer and use it in GitHub Desktop.
schizoid methods for python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ schizoid methods for python | |
| """ | |
| import inspect, new, sys | |
| # master registry for methodnames, decorators, and proxy scope dummy object | |
| registry = {} | |
| class proxy(object): pass | |
| def personalityDependant(func): | |
| """ we have to save func in the registry so each duplicate | |
| function name doesnt just overwrite the previous one | |
| NOTE: "whichSelf" is the name of the variable used where | |
| "self" is usually found in instancemethod definitions | |
| """ | |
| whichSelf = inspect.getargspec(func)[0][0] | |
| if whichSelf not in registry: registry[whichSelf] = {} | |
| registry[whichSelf][func.__name__] = func | |
| return func | |
| def schizophrenic(func): | |
| """ tag a function as schizophrenic so the metaclass knows when to | |
| effect the scope mangling. """ | |
| func.schizophrenic=True | |
| return func | |
| class schizotypal(type): | |
| """ metaclass for all schizoids """ | |
| @staticmethod | |
| def __new__(mcls, name, bases, clsdict): | |
| err1 ='expected a schizotypal object would have a list of personalities.' | |
| try: assert 'personalities' in clsdict | |
| except AssertionError: raise Exception, err1 | |
| else: | |
| personalities = clsdict['personalities'] | |
| replacement = {} | |
| for pName in personalities: replacement[pName] = registry[pName] | |
| personalities = replacement | |
| clsdict['personalities'] = personalities | |
| klassobj = type.__new__(mcls, name, bases, clsdict) | |
| return klassobj | |
| def __call__(cls, *args, **kargs): | |
| inst = type.__call__(cls, *args, **kargs) | |
| for var in dir(inst): | |
| val = getattr(inst, var) | |
| test = var!='__metaclass__' and var!='__class__' | |
| if hasattr(val, 'schizophrenic') and test: | |
| for pName in inst.personalities: | |
| val.func_globals[pName] = inst.as(pName) | |
| return inst | |
| class schizoid(object): | |
| """ base schizoid object (inherit from this) """ | |
| __metaclass__ = schizotypal | |
| personalities = [] | |
| def as(self, pName): | |
| """ obtain a representation of self with respect to some personality """ | |
| cls = self.__class__ | |
| err = 'illegal personality for '+str(cls) + ': ' + pName | |
| assert pName in cls.personalities, err | |
| out = cls.personalities[pName] | |
| P = proxy() | |
| for funcname in out: | |
| func = out[funcname] | |
| func = new.instancemethod(func,self,cls) | |
| setattr(P, funcname, func) | |
| return P | |
| class myschizoid(schizoid): | |
| """ a simple demo. | |
| note that without the decorators, each status() definition would simply | |
| overwrite the previous one. notice also under normal python semantics | |
| how theres no reason the philosopher names in the run() method should | |
| be in scope. | |
| """ | |
| personalities = ['kant','heidegger','wittgenstein','schlegel'] | |
| @personalityDependant | |
| def status(kant): return "a real pissant" | |
| @personalityDependant | |
| def status(heidegger): return "a boozy beggar" | |
| @personalityDependant | |
| def status(wittgenstein): return "beery swine" | |
| @personalityDependant | |
| def status(schlegel): return "schloshed" | |
| @schizophrenic | |
| def run(self): | |
| print 'kant:\t\t\t', kant.status() | |
| print 'heidegger:\t\t', heidegger.status() | |
| print 'wittgenstein:\t\t', wittgenstein.status() | |
| print 'schlegel:\t\t', schlegel.status() | |
| if __name__=='__main__': | |
| s = myschizoid() | |
| s.run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment