Re: Why won't this decorator work?



On Jul 2, 11:08 am, John Salerno <johnj...@xxxxxxxxx> wrote:
On Jul 2, 12:33 pm, MRAB <pyt...@xxxxxxxxxxxxxxxxxxx> wrote:



On 02/07/2011 17:56, John Salerno wrote:

I thought I had finally grasped decorators, but the error I'm getting
('str' type is not callable) is confusing me.

def move(roll):
return 'You moved to space {0}.'.format(roll)

<snip>


A decorator should return a callable.

Well, should typically return a callable, but there are exceptions...


This:

     @move
     def roll_die():
         return random.randint(1, 6)

is equivalent to this:

     def roll_die():
         return random.randint(1, 6)

     roll_die = move(roll_die)

You should be defining a function (a callable) and then passing it to a
decorator which returns a callable.

As it is, you're defining a function and then passing it to a decorator
which is returning a string. Strings aren't callable.

But why does the documentation say "The return value of the decorator
need not be callable"?

Well, because it need not be callable: i.e., if the return value is
not callable, that is perfectly legal. You very rarely want to return
something else, but an example of this is the @property decorator: it
returns a property object, which is not callable.

And why, if I remove the decorator and just
leave the two functions as if, does the call to move(roll_die()) work?
Isn't that what the decorator syntax is essentially doing?

No; instead it's doing the similar looking but quite different

move(roll_die)()

As you wrote it, move(roll_die) returns the string 'You moved to space
<function roll_die>.' which is not callable. You typically want
instead something like:

def move(roll):
# note that roll is a function, not a number
def wrapper():
result = roll()
print 'You moved to space {0}.'.format(result)
return result
return wrapper # which is a function

Now move returns a callable (the function 'wrapper') so move(roll_die)
is callable, and move(roll_die)() is legal.

Cheers - Chas
.



Relevant Pages

  • Re: Why wont this decorator work?
    ... But why does the documentation say "The return value of the decorator ... movereturns the string 'You moved to space ... # note that roll is a function, ... Now move returns a callable (the function 'wrapper') so move ...
    (comp.lang.python)
  • Re: Why wont this decorator work?
    ... But why does the documentation say "The return value of the decorator ... movereturns the string 'You moved to space ... # note that roll is a function, ... Now move returns a callable (the function 'wrapper') so move ...
    (comp.lang.python)
  • Re: Why wont this decorator work?
    ... the commented sentence is from the Python docs, ... A decorator should return a callable. ... you're defining a function and then passing it to a decorator ... which is returning a string. ...
    (comp.lang.python)
  • Re: multimethods decorator
    ... but the examples shows the functionality using ... The multimethod decorator needs the types of the arguments, and, if the ... And what will that string contains? ...
    (comp.lang.python)
  • Re: Rather than decorators, how about sections?
    ... "Paul Morrow" wrote in message ... The decorator mechanism is intended to include much more than this simple ... mutex lock/unlock wrapper ... input argument validation/typing wrapper ...
    (comp.lang.python)