On Jul 2, 11:08 am, John Salerno <johnj...@gmail.com> wrote: > On Jul 2, 12:33 pm, MRAB <pyt...@mrabarnett.plus.com> 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 -- http://mail.python.org/mailman/listinfo/python-list