Differences between revisions 2 and 3
Revision 2 as of 2005-05-05 02:25:55
Size: 1506
Editor: G9389
Comment:
Revision 3 as of 2005-11-18 08:58:52
Size: 1635
Editor: athalle5
Comment:
Deletions are marked like this. Additions are marked like this.
Line 14: Line 14:
def wrap(func, pre, post):
   def call(*args, **kwargs):
      pre(func, *args, **kwargs)
      result = func(*args, **kwargs)
      post(func, *args, **kwargs)
      return result
   return call
def wrap(pre, post):
    def decorate(func):
        def call(*args, **kwargs):
            pre(func, *args, **kwargs)
            result = func(*args, **kwargs)
            post(func, *args, **kwargs)
           return result
        return call
   return decorate
Line 22: Line 24:

The additional decorate function is needed to work with the Python 2.4 decorator syntax.
Line 32: Line 36:
@wrap(trace_in, trace_out)
Line 39: Line 44:
>>> f = wrap(calc, trace_in, trace_out)
Line 41: Line 45:
3
>>> print f(1, 2)

FunctionWrapper is a design pattern used when dealing with relatively complicated functions. The wrapper function typically performs some prologue and epilogue tasks like

  • allocating and disposing resources
  • checking pre- and post-conditions
  • caching / recycling a result of a slow computation

but otherwise it should be fully compatible with the wrapped function, so it can be used instead of it. (This is related to the DecoratorPattern.)

As of Python 2.1 and the introduction of nested scopes, wrapping a function is easy:

   1 def wrap(pre, post):
   2     def decorate(func):
   3         def call(*args, **kwargs):
   4             pre(func, *args, **kwargs)
   5             result = func(*args, **kwargs)
   6             post(func, *args, **kwargs)
   7            return result
   8         return call
   9    return decorate

The additional decorate function is needed to work with the Python 2.4 decorator syntax.

Now, let's wrap something up:

   1 def trace_in(func, *args, **kwargs):
   2    print "Entering function",  func.__name__
   3 
   4 def trace_out(func, *args, **kwargs):
   5    print "Leaving function", func.__name__
   6 
   7 @wrap(trace_in, trace_out)
   8 def calc(x, y):
   9    return x + y

The wrapping effect is:

   1 >>> print calc(1, 2)
   2 Entering function calc
   3 Leaving function calc
   4 3

Of course, a wrapper would normally perform some more useful task. Have a look [http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/412719 here] for a recipe how to wrap a function that processes files so that the result is recycled from a cache file if appropriate.

FunctionWrappers (last edited 2008-11-15 14:00:47 by localhost)

Unable to edit the page? See the FrontPage for instructions.