Using a decorator to *remove* parameters from a call

Aaron Brady castironpi at gmail.com
Mon Apr 13 06:45:27 EDT 2009


On Apr 13, 5:11 am, Michel Albert <exh... at gmail.com> wrote:
> A small foreword: This might look like a cherrypy-oriented post, and
> should therefore go to the cherrypy group, but if you read to the end,
> you'll see it's a more basic python problem, with cherrypy only as an
> example. ;)
>
> From the decorator PEP (318) I get it that you can /add/ parameters to
> a call. Say you do something like this:
>
> @mydeco( foo="bar" )
> def myfunc( hello ):
>    print foo, foo
snip
> I would prefer a syntax like this (http://python.pastebin.com/
> f462bc29c)
>
> class MyController(Controller):
>
>     @expose()
>     @skinnable
>     @translatable
>     def index(self):
>         return "Hello skinned world"
>
>     @expose()
>     @skinnable
>     @translatable
>     def foo(self):
>         return "bar"
>
snip
> more future proof.
snip

Sure.  Just pop the keywords you want from the dictionary, if they
exist.

def take_ab( fun ):
    def newfun( *ar, **kw ):
        aval= kw.pop( 'a', None )
        bval= kw.pop( 'b', None )
        print( 'aval %r and bval %r popped'% ( aval, bval ) )
        res= fun( *ar, **kw )
        return res
    return newfun

@take_ab
def f( c= 42, d= 'some' ):
    print( 'in f, c= %r, d= %r'% ( c, d ) )

f( a= 'paramA', b= 'paramB', c= 'other number' )

/Output:

aval 'paramA' and bval 'paramB' popped
in f, c= 'other number', d= 'some'

As you can see, 'a', 'b', and 'c' were passed to 'f', but 'f' only
received 'c', as well as its default value for 'd'.  So long as you
only need to pass by keyword, not position, it's pretty easy.  It's
harder if the parameter you want might have been passed by either, and
you need to remove it from whichever one it was passed by.



More information about the Python-list mailing list