Skip to content

Instantly share code, notes, and snippets.

@uniphil
Last active August 29, 2015 13:57
Show Gist options
  • Save uniphil/9457265 to your computer and use it in GitHub Desktop.
Save uniphil/9457265 to your computer and use it in GitHub Desktop.
Python: decorated class super wat
"""
The class decorator screws up the inheritance, so super() gets confused and doesn't super superly.
"""
def make_awesome(cls):
class Awesomefied(cls):
"""make this class awesomer"""
return Awesomefied
class CoolParent(object):
def good_method(self):
"""This method is really good"""
def py3_woo(self):
"""Simpler super is nice and actually works"""
@make_awesome
class JustOkay(CoolParent):
def good_method(self):
super(JustOkay, self).good_method()
def py3_woo(self):
super().py3_woo()
okay = JustOkay()
okay.good_method() # inf. recursion in py2 and 3.
okay.py3_woo() # works in py3, not available in 2.
"""
If the class decorator needs to wrap methods, it can still do so by mutating the class object
directly, instead of inserting itself into the class hierarchy and screwing up super.
"""
def make_awesome(cls):
original_good = cls.good_method
def good_method(self):
return original_good(self)
cls.good_method = good_method
return cls
class CoolParent(object):
def good_method(self):
"""This method is really good"""
def py3_woo(self):
"""Simpler super is nice and actually works"""
@make_awesome
class JustOkay(CoolParent):
def good_method(self):
super(JustOkay, self).good_method()
def py3_woo(self):
super().py3_woo()
okay = JustOkay()
okay.good_method() # works for both woo
okay.py3_woo() # works in py3, not available in 2.
"""
DRY with the verbose method wrapping in the class decorator
"""
from functools import wraps, partial
def wrap_method_of(cls):
def wrapper(new_function):
method_name = new_function.__name__
original_method = getattr(cls, method_name)
@wraps(new_function)
def wrapped(self, *args, **kwargs):
super_ish = partial(original_method, self)
return new_function(super_ish, self, *args, **kwargs)
setattr(cls, method_name, wrapped)
return wrapped
return wrapper
def make_awesome(cls):
@wrap_method_of(cls)
def good_method(super_ish, self):
return super_ish()
return cls
class CoolParent(object):
def good_method(self):
"""This method is really good"""
@make_awesome
class JustOkay(CoolParent):
def good_method(self):
super(JustOkay, self).good_method()
okay = JustOkay()
okay.good_method()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment