Python Wrap Class Method
What other folks do
class A:
def do_run( self ):
"""Must be overridden."""
raise NotImplementedError
def run( self, *args, **kw ):
"""Must not be overridden.
You were warned.
"""
print "PRE"
return_value = self.do_run(*args, **kw)
print "POST"
return return_value
class B(A):
def do_run(self):
print "Run B"
return True
That's usually sufficient.
If you want to worry about someone "breaking" this, stop now. Don't waste time worrying.
It's Python. We're all adults here. All the malicious sociopaths will break all you code by copying it, changing it, and then breaking it. No matter what you do, they'll just copy your code and modify it to break the clever bits.
Everyone else will read your comment and stick by your rules. If they want to use your module/package/framework, they will cooperate.
Use a Metaclass.
class MetaClass(type):
@staticmethod
def wrap(run):
"""Return a wrapped instance method"""
def outer(self):
print "PRE",
return_value = run(self)
print "POST"
return return_value
return outer
def __new__(cls, name, bases, attrs):
"""If the class has a 'run' method, wrap it"""
if 'run' in attrs:
attrs['run'] = cls.wrap(attrs['run'])
return super(MetaClass, cls).__new__(cls, name, bases, attrs)
class MyClass(object):
"""Use MetaClass to make this class"""
__metaclass__ = MetaClass
def run(self): print 'RUN',
myinstance = MyClass()
# Prints PRE RUN POST
myinstance.run()
Now if other people subclass MyClass
, they will still get their run()
methods wrapped.
Easiest way: make run
the wrapper, and a private method be the overrideable one.
class A(object):
def run(self):
print "PRE"
return_value = self._inner_run()
print "POST"
return return_value
def _inner_run(self):
print "Run A"
return True
class B(A):
def _inner_run(self):
print "Run B"
return True