Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #8671 > unrolled thread

Why won't this decorator work?

Started byJohn Salerno <johnjsal@gmail.com>
First post2011-07-02 09:56 -0700
Last post2011-07-02 19:14 -0700
Articles 16 — 9 participants

Back to article view | Back to comp.lang.python


Contents

  Why won't this decorator work? John Salerno <johnjsal@gmail.com> - 2011-07-02 09:56 -0700
    Re: Why won't this decorator work? MRAB <python@mrabarnett.plus.com> - 2011-07-02 18:33 +0100
      Re: Why won't this decorator work? John Salerno <johnjsal@gmail.com> - 2011-07-02 11:08 -0700
        Re: Why won't this decorator work? Tim Chase <python.list@tim.thechases.com> - 2011-07-02 13:45 -0500
          Re: Why won't this decorator work? John Salerno <johnjsal@gmail.com> - 2011-07-02 13:39 -0700
            Re: Why won't this decorator work? Ben Finney <ben+python@benfinney.id.au> - 2011-07-03 08:36 +1000
            Re: Why won't this decorator work? "OKB (not okblacke)" <brenNOSPAMbarn@NObrenSPAMbarn.net> - 2011-07-03 18:01 +0000
              Re: Why won't this decorator work? John Salerno <johnjsal@gmail.com> - 2011-07-03 20:24 -0700
              Re: Why won't this decorator work? Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2011-07-04 20:22 +1200
        Re: Why won't this decorator work? Ian Kelly <ian.g.kelly@gmail.com> - 2011-07-02 12:49 -0600
          Re: Why won't this decorator work? Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2011-07-03 16:14 +1200
        Re: Why won't this decorator work? ChasBrown <cbrown@cbrownsystems.com> - 2011-07-02 12:16 -0700
        Re: Why won't this decorator work? ChasBrown <cbrown@cbrownsystems.com> - 2011-07-02 12:17 -0700
        Re: Why won't this decorator work? ChasBrown <cbrown@cbrownsystems.com> - 2011-07-02 12:16 -0700
        Re: Why won't this decorator work? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-07-03 12:11 +1000
          Re: Why won't this decorator work? John Salerno <johnjsal@gmail.com> - 2011-07-02 19:14 -0700

#8671 — Why won't this decorator work?

FromJohn Salerno <johnjsal@gmail.com>
Date2011-07-02 09:56 -0700
SubjectWhy won't this decorator work?
Message-ID<8b8c3ca2-ae36-4009-842e-1dc90fb01b65@ct4g2000vbb.googlegroups.com>
I thought I had finally grasped decorators, but the error I'm getting
('str' type is not callable) is confusing me. Here is my code. Also,
the commented sentence is from the Python docs, which says it doesn't
even need to be callable, if that matters. I also commented out a few
things in the move method. They were just to see if it would work, but
those lines raised even more errors!

import random

#space = 0

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

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

# The return value of the decorator need not be callable
# roll_die = move(roll_die)



I tried running the command "roll_die()" and I get the error message.

Thanks.

[toc] | [next] | [standalone]


#8672

FromMRAB <python@mrabarnett.plus.com>
Date2011-07-02 18:33 +0100
Message-ID<mailman.561.1309628013.1164.python-list@python.org>
In reply to#8671
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. Here is my code. Also,
> the commented sentence is from the Python docs, which says it doesn't
> even need to be callable, if that matters. I also commented out a few
> things in the move method. They were just to see if it would work, but
> those lines raised even more errors!
>
> import random
>
> #space = 0
>
> def move(roll):
> #    global space
> #   space += roll
>      return 'You moved to space {0}.'.format(roll)
>
> @move
> def roll_die():
>      return random.randint(1, 6)
>
> # The return value of the decorator need not be callable
> # roll_die = move(roll_die)
>
>
>
> I tried running the command "roll_die()" and I get the error message.
>
> Thanks.

A decorator should return a callable.

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.

[toc] | [prev] | [next] | [standalone]


#8675

FromJohn Salerno <johnjsal@gmail.com>
Date2011-07-02 11:08 -0700
Message-ID<98cca0c2-8d4f-4313-abed-3f34fa165c6d@u28g2000yqf.googlegroups.com>
In reply to#8672
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. Here is my code. Also,
> > the commented sentence is from the Python docs, which says it doesn't
> > even need to be callable, if that matters. I also commented out a few
> > things in the move method. They were just to see if it would work, but
> > those lines raised even more errors!
>
> > import random
>
> > #space = 0
>
> > def move(roll):
> > #    global space
> > #   space += roll
> >      return 'You moved to space {0}.'.format(roll)
>
> > @move
> > def roll_die():
> >      return random.randint(1, 6)
>
> > # The return value of the decorator need not be callable
> > # roll_die = move(roll_die)
>
> > I tried running the command "roll_die()" and I get the error message.
>
> > Thanks.
>
> A decorator should return a callable.
>
> 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"? 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?

[toc] | [prev] | [next] | [standalone]


#8677

FromTim Chase <python.list@tim.thechases.com>
Date2011-07-02 13:45 -0500
Message-ID<mailman.562.1309632366.1164.python-list@python.org>
In reply to#8675
On 07/02/2011 01:08 PM, John Salerno wrote:
> On Jul 2, 12:33 pm, MRAB<pyt...@mrabarnett.plus.com>  wrote:
>>       roll_die = move(roll_die)
>>
>> You should be defining a function (a callable) and then passing it to a
>> decorator which returns a callable.
>
> But why does the documentation say "The return value of the decorator
> need not be callable"?

I must not be looking at the same documentation you are...could 
you provide a link? The only time I know of that the return value 
of a decorator need not be callable is if you want to totally 
break the syntax of the function. :-/

> 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?

Are you doing

   move(roll_die()) #call roll_die() and pass results to move()

or

   move(roll_die) # pass the function-object roll_die to move()

?  The decorator syntax is the equivalent of

   roll_die = move(roll_die)

-tkc


[toc] | [prev] | [next] | [standalone]


#8683

FromJohn Salerno <johnjsal@gmail.com>
Date2011-07-02 13:39 -0700
Message-ID<a61a8a98-609a-4fb2-ba1a-45c9c1a374db@w4g2000yqm.googlegroups.com>
In reply to#8677
On Jul 2, 1:45 pm, Tim Chase <python.l...@tim.thechases.com> wrote:

> I must not be looking at the same documentation you are...could
> you provide a link? The only time I know of that the return value
> of a decorator need not be callable is if you want to totally
> break the syntax of the function. :-/

http://docs.python.org/py3k/whatsnew/2.4.html?highlight=decorator

Sort of around the middle of the PEP 318 section.

But I think I understand now. I was thinking the decorator I made was
creating move(roll_die()), which I see now that it is not. Perhaps a
decorator isn't what I need in my case, although it seems like it
might be.

Basically what I want to do is this: I first to need to roll a die to
get a random number, then pass that number to the move method of a
Player class. Can this be done with a decorator, or is it better just
to do it like move(roll_die()) and be done with it?

[toc] | [prev] | [next] | [standalone]


#8689

FromBen Finney <ben+python@benfinney.id.au>
Date2011-07-03 08:36 +1000
Message-ID<87y60gjon4.fsf@benfinney.id.au>
In reply to#8683
John Salerno <johnjsal@gmail.com> writes:

> Basically what I want to do is this: I first to need to roll a die to
> get a random number, then pass that number to the move method of a
> Player class. Can this be done with a decorator, or is it better just
> to do it like move(roll_die()) and be done with it?

If what you want can be expressed with ‘player.move(roll_die())’, I'm
confused as to why you think decorators would help.


A decorator is syntactic sugar for something quite different::

    @foo(spam, eggs)
    @bar
    def baz(beans):
        """ … """

is equivalent to::

    def baz(beans):
        """ … """

    baz = foo(spam, eggs)(bar(baz))

except in the first instance, the function defined never gets bound to
the name ‘baz’ even temporarily.

* The function ‘baz’ is defined, resulting in a function object. (In the
  first example, it is never bound to the name ‘baz’.)

* The expression ‘bar’ is evaluated, and the result (probably a function
  named ‘bar’) is called with the function object defined as ‘baz’; the
  return value should be a new function.

* The expression ‘foo(spam, eggs)’ is evaluated, and the result (the
  return value from that function call) is itself called, passing the
  return value from the call to ‘bar’.

* Finally, the return value from all of that is bound to the name ‘baz’.

Note that, in both ways of writing that, ‘baz’ is never called, but
instead the function object ‘baz’ is used as a parameter. Also, the
original function defined as ‘baz’ is no longer accessible.


That seems quite unrelated to your stated requirements. If you're not
accustomed to passing function objects around as data, that can be
difficult to wrap your head around; if you didn't know you needed it,
you probably don't in this case.

-- 
 \     “Jealousy: The theory that some other fellow has just as little |
  `\                                         taste.” —Henry L. Mencken |
_o__)                                                                  |
Ben Finney

[toc] | [prev] | [next] | [standalone]


#8733

From"OKB (not okblacke)" <brenNOSPAMbarn@NObrenSPAMbarn.net>
Date2011-07-03 18:01 +0000
Message-ID<Xns9F17708D7849COKB@88.198.244.100>
In reply to#8683
John Salerno wrote:

> Basically what I want to do is this: I first to need to roll a die to
> get a random number, then pass that number to the move method of a
> Player class. Can this be done with a decorator, or is it better just
> to do it like move(roll_die()) and be done with it?

    	A decorator basically modifies a function/method, so that ALL 
subsequent calls to it will behave differently.  If you want ALL calls 
to your method to roll a die to get a random number, and then use that 
random number, why not just roll the die inside the method itself:

def move(dist=None):
    	if dist=None:
    	    	dist = random.randint(1, 7)
    	# etc

    	If you don't want all calls to your method to roll the die, but 
only some, and if the choice of whether to roll or not depends on 
information outside the method, then you need to do the rolling outside 
the method and pass the result in.  This is more or less what other 
people have mentioned (and what you seem to have also been considering):

# In code that wants to move the player. . .
if doIWantToMoveRandomly():
    	player.move(rollDie())
else:
    	player.move(2) # or whatever non-random expression you want

-- 
--OKB (not okblacke)
Brendan Barnwell
"Do not follow where the path may lead.  Go, instead, where there is
no path, and leave a trail."
	--author unknown

[toc] | [prev] | [next] | [standalone]


#8752

FromJohn Salerno <johnjsal@gmail.com>
Date2011-07-03 20:24 -0700
Message-ID<aadb4ff5-1ae5-4658-b6fb-263ac9cbd2dd@hi9g2000vbb.googlegroups.com>
In reply to#8733
On Jul 3, 1:01 pm, "OKB (not okblacke)"
<brenNOSPAMb...@NObrenSPAMbarn.net> wrote:

> subsequent calls to it will behave differently.  If you want ALL calls
> to your method to roll a die to get a random number, and then use that
> random number, why not just roll the die inside the method itself:

I thought maybe it would be cleaner if the roll function was something
separate, but I suppose it could go inside the move method. It just
seemed like two different things that needed to be separated.

[toc] | [prev] | [next] | [standalone]


#8758

FromGregory Ewing <greg.ewing@canterbury.ac.nz>
Date2011-07-04 20:22 +1200
Message-ID<97dbigF4d1U1@mid.individual.net>
In reply to#8733
OKB (not okblacke) wrote:

>     	A decorator basically modifies a function/method, so that ALL 
> subsequent calls to it will behave differently.

Furthermore, usually a decorator is used when for some
reason you *can't* achieve the same effect with code
inside the function itself.

For example, the classmethod() and staticmethod()
decorators return descriptors that have different
magical effects from a standard function object when
looked up in a class or instance. Since that magic
happens *before* the function is called, you can't
do the same thing using an ordinary function.

In this case, an ordinary function is quite sufficient,
and there is no need to involve a decorator.

-- 
Greg

[toc] | [prev] | [next] | [standalone]


#8678

FromIan Kelly <ian.g.kelly@gmail.com>
Date2011-07-02 12:49 -0600
Message-ID<mailman.563.1309632586.1164.python-list@python.org>
In reply to#8675
On Sat, Jul 2, 2011 at 12:08 PM, John Salerno <johnjsal@gmail.com> wrote:
> But why does the documentation say "The return value of the decorator
> need not be callable"?

Because the language does not enforce the restriction that the return
value should be a callable.  If it's not a callable, then the result
will just be that something non-callable is bound to the "roll_die"
name -- which could be useful, but is probably a bad idea in general.

> 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.  The decorator syntax is doing:

roll_die = move(roll_die)

If you then call roll_die, that is equivalent to "move(roll_die)()",
which is not the same thing as "move(roll_die())".

Cheers,
Ian

[toc] | [prev] | [next] | [standalone]


#8723

FromGregory Ewing <greg.ewing@canterbury.ac.nz>
Date2011-07-03 16:14 +1200
Message-ID<97a8l3F39sU1@mid.individual.net>
In reply to#8678
Ian Kelly wrote:
> If it's not a callable, then the result
> will just be that something non-callable is bound to the "roll_die"
> name -- which could be useful, but is probably a bad idea in general.

There are legitimate uses -- for example, the following
is a convenient way of creating a read-only property:

   @property
   def foo(self):
     return self.calculate_value_of_foo()

-- 
Greg

[toc] | [prev] | [next] | [standalone]


#8679

FromChasBrown <cbrown@cbrownsystems.com>
Date2011-07-02 12:16 -0700
Message-ID<d7342e12-53f2-4492-a872-edd32333817d@17g2000prr.googlegroups.com>
In reply to#8675
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

[toc] | [prev] | [next] | [standalone]


#8680

FromChasBrown <cbrown@cbrownsystems.com>
Date2011-07-02 12:17 -0700
Message-ID<4df5c388-9e99-4b7d-93ec-968054f1871a@x38g2000pri.googlegroups.com>
In reply to#8675
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

[toc] | [prev] | [next] | [standalone]


#8681

FromChasBrown <cbrown@cbrownsystems.com>
Date2011-07-02 12:16 -0700
Message-ID<c68bb6c6-4a8a-47fe-80bf-4fd5af7c8c1b@q14g2000prh.googlegroups.com>
In reply to#8675
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

[toc] | [prev] | [next] | [standalone]


#8708

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2011-07-03 12:11 +1000
Message-ID<4e0fcfdf$0$29969$c3e8da3$5496439d@news.astraweb.com>
In reply to#8675
John Salerno wrote:

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

The thing returned by a decorator does not need to be callable, but if you
want to call it, then it better be!

This is no different from this:

my_func = "hello world"
my_func()  # fails because strings aren't callable

So if I do this:

def decorator(func):
    # ignores the function and returns a string
    return "hello world"

@decorator
def my_func():
    x = 1
    y = 2
    return x+y

print(my_func)  # prints "hello world"
my_func()  # fails because strings aren't callable


If that's useful to you, decorator syntax allows it. That is all the
documentation means.



> 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?

The call move(roll_die()) is similar to this:

temp = roll_die()
my_string = move(temp)

which is perfectly fine, because you never call my_string. If you did, you'd
get the same error, because strings aren't callable.

The decorator syntax is completely different. It is doing this:

# replace the function roll_die with the output of move, which is a string
roll_die = move(roll_die)  
# now try to call "roll_die", actually a string
roll_die()

which is more like:

move(roll_die)()

See the difference?



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#8709

FromJohn Salerno <johnjsal@gmail.com>
Date2011-07-02 19:14 -0700
Message-ID<fbbc1823-7679-4e7f-b097-13b35a320e58@t9g2000vbv.googlegroups.com>
In reply to#8708
On Jul 2, 9:11 pm, Steven D'Aprano <steve
+comp.lang.pyt...@pearwood.info> wrote:
> John Salerno wrote:
> > But why does the documentation say "The return value of the decorator
> > need not be callable"?
>
> The thing returned by a decorator does not need to be callable, but if you
> want to call it, then it better be!
>
> This is no different from this:
>
> my_func = "hello world"
> my_func()  # fails because strings aren't callable
>
> So if I do this:
>
> def decorator(func):
>     # ignores the function and returns a string
>     return "hello world"
>
> @decorator
> def my_func():
>     x = 1
>     y = 2
>     return x+y
>
> print(my_func)  # prints "hello world"
> my_func()  # fails because strings aren't callable
>
> If that's useful to you, decorator syntax allows it. That is all the
> documentation means.
>
> > 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?
>
> The call move(roll_die()) is similar to this:
>
> temp = roll_die()
> my_string = move(temp)
>
> which is perfectly fine, because you never call my_string. If you did, you'd
> get the same error, because strings aren't callable.
>
> The decorator syntax is completely different. It is doing this:
>
> # replace the function roll_die with the output of move, which is a string
> roll_die = move(roll_die)  
> # now try to call "roll_die", actually a string
> roll_die()
>
> which is more like:
>
> move(roll_die)()
>
> See the difference?
>
> --
> Steven

Eesh, ok, I think I *still* don't quite get decorators, but I get it a
little more now. Definitely not what I needed to do here. :)

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web