Created
March 8, 2013 17:38
-
-
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.
This file contains 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
'''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