* Stephen Hansen, on 02.07.2010 19:41:
Okay, so!

I actually never quite got around to learning to do deep and useful
magic with decorators. I've only ever done the most basic things with
them. Its all been a little fuzzy in my head: things like what order
decorators end up being called in if there's more then one, etc.

But in my current situation, what I'm wanting to do is have a decorator
that wraps a function but which takes an *optional* argument, and sets
that argument as an attribute on said function if its there.

Here's what some tweaking and playing around has gotten me, as a recipe:

     import functools

     def my_decorator(arg):
         if callable(arg): # Stuck on 2.5. Leavemealone. :)
             protocol = None
         else:
             protocol = arg

         def wrap(fn):
             print "Wrapping."
             fn.protocol = protocol

             @functools.wraps(fn)
             def wrapper(*args, **kwargs):
                 print "Calling."
                 result = fn(*args, **kwargs)
                 print "Called."
                 return result

             return wrapper

         if not protocol: # argument-less decorator
             print "Calling wrap."
             return wrap(arg)
         else:
             print "Returning wrap."
             return wrap

To be used as:

     class Thing(object):
         @expose
         def test1(self, arg1):
             return arg1

         @expose("testing")
         def test2(self, arg2):
             return arg2

So, my question: am I doing this right? :) Some play-through testing
appears to work. But, the dizzying array of nested def's up there leaves
me a bit dazed, so I'm wondering if there's a simpler way to accomplish
what I'm trying to do.

If you're willing to have slightly more explicit usage code, consider e.g.


<code>
#Py3

import functools

class expose:
    def __init__( self, protocol = None ):
        self._protocol = protocol

    def __call__( self, f ):
        print( "Wrapping." )
        f.protocol = self._protocol

        @functools.wraps( f )
        def wrapper( *args, **kwargs ):
            print( "Calling." )
            result = f( *args, **kwargs )
            print( "Called." )
            return result

        return wrapper

class Thing(object):
    @expose()
    def test1(self, arg1):
        return arg1

    @expose( "testing" )
    def test2(self, arg2):
        return arg2

o = Thing()
print( o.test1( 1.11 ) )
print( o.test2( 2.22 ) )
</code>


Cheers & hth.,

- Alf


--
blog at <url: http://alfps.wordpress.com>
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to