I find I am still left asking the question "why would anyone want to do that?".On Wed, 06 Apr 2005 08:10:22 GMT, [EMAIL PROTECTED] (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--
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/
-- http://mail.python.org/mailman/listinfo/python-list