Decorator Base Class: Needs improvement.

Steve Holden steve at holdenweb.com
Wed Apr 6 15:05:26 EDT 2005


Ron_Adam wrote:
> On Wed, 06 Apr 2005 08:10:22 GMT, bokr at oz.net (Bengt Richter) wrote:
> 
> 
>>I don't understand your seeming fixation with wrappers and wrapping.
> 
> 
> Fixated implies, I'm stuck on a single thing, but I'm not. I am
> learning as I go, and exploring some possibilities as well.  :-)
> 
> 
>>That's not
>>the only use for decorators. See Raymond Hettinger's optimizing decorators
>>in the cookbook for instance. 
> 
> 
> Thanks, I'll look for it.  Is it in the new edition?  I haven't picked
> it up yet.
> 
> 
>>Decorators are something like metaclasses for functions,
>>with much more general possibilities than wrapping, IMO.
> 
> 
> I'm not sure I see the metaclass relation.  What more general things
> can be done with Decorators, that can't be done with a wrapper?
> 
> Wrapping, and the @decorator expressions, interest me because I see a
> lot of potential in it's use, and so I'm trying to learn them, and at
> the same time, there are things about the @ expression that seems (to
> me), that it's not the most practical way to do what it was intended
> for.  
> 
> On the plus side, it's kind of cute with the little curly thing
> propped up on top of the function. It's a neat trick that it does what
> it does with a minimal amount of changes to the language by taking
> advantage of pythons existing function perimeter and object passing
> properties. It saves a bit of typing because we don't have to retype
> the function name a few times.  (Several people have referred to it as
> 'sugar', and now I am starting to agree with that opinion.)
> 
> On the minus side, it's not intuitive to use.  It is attached to the
> function definitions so they are limited, they can't be easily
> unwrapped and rewrapped without redefining the function also.  The
> recursive nature of stacked @ statements is not visible.
> 
> So my opinion of @ as a whole is currently: -1
> 
> 
> 
>>I think you'll have to show some convincing use cases showing a clear
>>advantage over current decoration coding if you want converts ;-)
> 
> 
> What about the following?  :-)
> 
> # Using this simple wrapper class:
> class wrapper(object):
>     def __call__(self,x):
>        # preprocess x
>        x*=2 			# Make a change so we can see it
>        result = self.function(x)
>        # postprocuess result
>        return result
> 
> # A function to apply the wrapper:
> def wrap(function,wrapper):
>     w = wrapper()
>     w.function = function
>     return w
> 
> # The function
> def fn(x):
>     return x
> 
> print fn(5)		# Before
> 
> # Wrapit.
> fn = wrap(fn,wrapper)
> 
> print fn(5)		# After
> 
> # Unwrap it.
> fn = fn.function
> 
> print fn(5)     # And back again
> 
> #prints
> #5
> #10
> #5
> 
> It has several advantages over @ expression.  It doesn't need the
> triple nested defines to get the function name and argument list, the
> wrapper is simpler, It can be placed on a function and then removed,
> when and where it's needed, instead of at the point where the function
> is defined.
> 
> The following behaves more closely to the existing @ expression in
> that it has the same nesting behavior for stacked wrappers.  
> 
> I'm looking into a way to do sequential non-nested stacked wrappers at
> this point, where the output of one goes to the input of the next.
> That can't be done currently with the @ decorator expression.
> 
> This stacks a list of 10 wrappers on 10 different functions and
> reverses the order of the stack every other function. In this case
> they are all the same, but they could all be differnt. 
> 
> Cheers,
> Ron
> 
> #---start---
> class wrapper(object):
>     def __call__(self,*x):
>         # preprocess
>         x = [x[0]+1,] 
>         print 'preprocess', x[0], self.args
>         # call function
>         result = self.function(*x)
>         # postprocess
>         result +=1
>         print 'postprocess', result, self.args
>         return result
> 
> def wrap(f,w,shape='forward'):
>     if shape=='reverse':
>         w.reverse()
>     for ww in w:
>         nw = wrapper()
>         try:
>             nw.args = ww[1]
>         except TypeError:
>             wf = ww[0]
>         nw.function = f
>         f = nw
>     return f
> 
> # Make a list of ten wrappers with an id number as an additional
> # wrapper perimeter.
> w = []
> for n in xrange(10):
>     w.append((wrapper,n))
>     
> # Wrap 10 functions, 10 times, in reversing order.
> def func0(x): return x
> def func1(x): return x
> def func2(x): return x
> def func3(x): return x
> def func4(x): return x
> def func5(x): return x
> def func6(x): return x
> def func7(x): return x
> def func8(x): return x
> def func9(x): return x
> 
> func0 = wrap(func0,w)
> func1 = wrap(func1,w,'reverse')
> func2 = wrap(func2,w)
> func3 = wrap(func3,w,'reverse')
> func4 = wrap(func4,w)
> func5 = wrap(func5,w,'reverse')
> func6 = wrap(func6,w)
> func7 = wrap(func7,w,'reverse')
> func8 = wrap(func8,w)
> func9 = wrap(func9,w,'reverse')
> 
> print func0(0)
> print func1(0)
> print func2(0)
> print func3(0)
> print func4(0)
> print func5(0)
> print func6(0)
> print func7(0)
> print func8(0)
> print func9(0)
> 
> #--end--
> 
> 
> 
I find I am still left asking the question "why would anyone want to do 
that?".

The difference between a use case and an example is that a use case 
should demonstrate the solution of a problem that someone might 
reasonably be wanting to solve, rather than a way of creating an 
abstract program structure for which there is no easily observable 
requirement.

I can understand it if you are merely pursuing this topic because of 
your fascination with the capabilities of Python, but I don't have the 
feeling that there are legion Python programmers out there waiting 
impatiently to be able to build wrapped functions. People have been 
doing that as necessary for years, you're just coming to it for the 
first time.

By the way, we pass *parameters* to functions, *perimeters* surround things.

regards
  Steve
-- 
Steve Holden        +1 703 861 4237  +1 800 494 3119
Holden Web LLC             http://www.holdenweb.com/
Python Web Programming  http://pydish.holdenweb.com/




More information about the Python-list mailing list