Last active
August 29, 2015 13:57
-
-
Save uniphil/9457265 to your computer and use it in GitHub Desktop.
Python: decorated class super wat
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
""" | |
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. |
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
""" | |
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. |
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
""" | |
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