Skip to content

Instantly share code, notes, and snippets.

@mattvonrocketstein
Created September 14, 2010 01:27
Show Gist options
  • Select an option

  • Save mattvonrocketstein/578382 to your computer and use it in GitHub Desktop.

Select an option

Save mattvonrocketstein/578382 to your computer and use it in GitHub Desktop.
schizoid methods for python
""" 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
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()
print
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