On 6/17/07, voltron <[EMAIL PROTECTED]> wrote:
>
> I´m no decorator guru myself, but i dont think that decorators have to
> return functions necessarily. But I had also tried what you suggested,
> that gives me an exception:
>
> exceptions.TypeError: 'NoneType' object is not callable
>
>
> On Jun 17, 10:05 am, Christoph Haas <[EMAIL PROTECTED]> wrote:
> > On Sun, Jun 17, 2007 at 12:47:47AM -0700, voltron wrote:
> > > I am having problems using decorators with controllers. In a test
> > > controller:
> >
> > > # testcontroller.py
> >
> > > def dec(func):
> > >     # do lotsa things
> > >     print "im doing something"
> > >     finished = True
> > >     if finished:
> > >         func() # call the function you were decorating
> >
> > > class HomeController(BaseController):
> > >     def index(self):
> > >         return render_response('index.html')
> >
> > >     @dec(home)
> > >     def test(self):
> > >         return render_response('test.html')
> >
> > > tryinf this, I get an error:
> > > exceptions.TypeError: home() takes exactly 1 argument (0 given)
> >
> > > I have to pass "self" to the function passed to the decorator somehow,
> > > what would be the best way to do this? I want the decorator to carry
> > > out a few things before calling the controller function its
> > > decorating.
> >
> > I'm no decoration guru. But don't you have to "return func" in the
> > decorator?

Decorators are tricky enough themselves, but decorators with arguments
are even more tricky.  I haven't tried to write one but from what I
understand, the main job of a decorator is to define a *local*
function which calls the wrapped function, and then return the local
function.  So you have to replace your decorator with:

def dec(func):
    def newfunc():
        print "About to call decorated function %s." % func.func_name
        rslt = func()
        print "Finished calling decorated function %s, result = %r." %
(func.func_name, rslt)
        return rslt
    return newfunc

@dec
def test(...):  ...

I don't understand what you're intending to do with 'home' and
'finished', so I can't put them in my example.

If you put arguments in the @ line, it's a decorator factory; i.e., it
*returns* a decorator rather than "being" a decorator.  Typically this
means an additional level of local def, something like this:

def factory(context):
    def dec(func):
        print "I am doing something wonderful with %r." % context
        def newfunc():
            print "About to call decorated function."
            print "I could do something with 'context'."
            print "Maybe I can even pass 'context' to 'func'?"
            rslt = func()
            print "Finished calling decorated function."
            return rslt

@dec(home)
def test(...): ...

The two cases are consistent if you realize that the part following @
is an expression: whatever it evaluates to is the decorator.  A
function with arguments is a function call: the return value is the
decorator.  A function without () is a function reference: the
function itself is the decorator.

The definitive spec for decorators  is
http://python.org/dev/peps/pep-0318/ .  The Nose package has several
decorators with arguments n the 'nose.tools' module.  They're pretty
straightforward so they'd be good to study.

-- 
Mike Orr <[EMAIL PROTECTED]>

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"pylons-discuss" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/pylons-discuss?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to