Skip to content

Instantly share code, notes, and snippets.

@twneale
Created March 8, 2013 17:38
Show Gist options
  • Save twneale/5118262 to your computer and use it in GitHub Desktop.
Save twneale/5118262 to your computer and use it in GitHub Desktop.
Make a nested class definition inherit the attributes of the class in whose scope it was defined.
'''Make a nested class definition inherit the attributes of
the class in whose scope it was defined.
'''
class Context(object):
'''Base type for Context objects.
'''
pass
class ChildContext(object):
'''Special descriptor wrapper for child context
classes.
'''
def __init__(self, member):
self.member = member
def __get__(self, obj, objtype):
try:
return self.child_type
except AttributeError:
pass
member = self.member
name = member.__name__
attrs = dict(parent=obj, __metaclass__=ContextMeta)
child_type = type(name, (member, objtype), attrs)
self.child_type = child_type
return child_type
class ContextMeta(type):
def __new__(meta, name, bases, attrs):
for attr, member in attrs.items():
# Wrap any Context subclasses in ChildContext
# descriptors.
try:
if issubclass(member, Context):
attrs[attr] = ChildContext(member)
except TypeError:
# The member wasn't a class object.
continue
return type.__new__(meta, name, bases, attrs)
class Context(Context):
__metaclass__ = ContextMeta
class ContextMeta(type):
'''Overwrite ContextMeta, which has already been invoked in
all Context class definitions by this point, so that the
ChildContext descriptor will have a valid metaclass subtype
to use in subclassing the child context.
'''
__new__ = type.__new__
# And now to use it.
class Person(Context):
def print_bio(self):
print self.first_name, self.last_name, 'likes', self.fave_food
class Thom(Person):
first_name = 'Thom'
last_name = 'Neale'
fave_food = 'mac n cheese'
class Jacob(Person):
first_name = 'Jacob'
fave_food = 'grapes'
Thom().print_bio()
Thom().Jacob().print_bio()
import pdb; pdb.set_trace()
# This prints:
# Thom Neale likes mac n cheese
# Jacob Neale likes grapes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment