im7
im7

Reputation: 673

Function in Python gives error message

I am learning Python and I am reading the "Think Python" and doing some simple exercises included in the book.

I am asked "Define a new function called do_four that takes a function object and a value and calls the function four times, passing the value as a parameter."

I am trying to compose this function with one statement by calling a function already defined called do_twice() and test it with a function called print_double(). Here is the code:

def do_twice(f, x): 
    f(x) 
    f(x)

def do_four(f, v):
    do_twice(do_twice(f, v), v)

def print_twice(s): 
    print s
    print s

s = 'abc'

do_four(print_twice, s)

This code produces an error:

abc
abc
abc
abc
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-41-95b513e5e0ee> in <module>()
----> 1 do_four(print_twice, s)

<ipython-input-40-100f8587f50a> in do_four(f, v)
      1 def do_four(f, v):
----> 2     do_twice(do_twice(f, v), v)

<ipython-input-38-7143620502ce> in do_twice(f, x)
      1 def do_twice(f, x):
----> 2     f(x)
      3     f(x)

TypeError: 'NoneType' object is not callable

In trying to understand what is happening I tried to construct a Stack Diagram as described in the book. Here it is:

enter image description here

Could you explain the error message and comment on the Stack Diagram?

Your advice will be appreciated.

Upvotes: 2

Views: 280

Answers (2)

Israel Unterman
Israel Unterman

Reputation: 13510

do_twice gets a function on the first argument, and doesn't return anything. So there is no reason to pass do_twice the result of do_twice. You need to pass it a function.

This would do what you meant:

def do_four(f, v):
    do_twice(f, v)
    do_twice(f, v)

Very similar to how you defined do_twice by f

Upvotes: 2

deceze
deceze

Reputation: 522110

do_twice(do_twice(f, v), v)
         ^^^^^^^^^^^^^^

Slightly rewritten:

result = do_twice(f, v)
do_twice(result, v)

You're passing the return value of do_twice(...) as the first parameter to do_twice(...). That parameter is supposed to be a function object. do_twice does not return anything, so result is None, which you're passing instead of the expected function object.

There's no point in nesting the two do_twice in any way here.

Upvotes: 1

Related Questions