我有这些函数,并且我遇到错误,使用do_twice函数,但我在调试时遇到问题
#!/usr/bin/python
#functins exercise 3.4
def do_twice(f):
f()
f()
def do_four(f):
do_twice(f)
do_twice(f)
def print_twice(str):
print str + 'one'
print str + 'two'
str = 'spam'
do_four(print_twice(str))
调试器错误
:!python 'workspace/python/functions3.4.py'
spamone
spamtwo
Traceback (most recent call last):
File "workspace/python/functions3.4.py", line 18, in <module>
do_four(print_twice(str))
File "workspace/python/functions3.4.py", line 9, in do_four
do_twice(f)
File "workspace/python/functions3.4.py", line 5, in do_twice
f()
TypeError: 'NoneType' object is not callable
shell returned 1
答案 0 :(得分:11)
问题是表达式print_twice(str)
是通过使用print_twice
调用str
并获得返回的结果来评估的,*结果就是您作为参数传递的结果到do_four
。
您需要传递给do_four
的是一个函数,在调用时会调用print_twice(str)
。
您可以手动构建此类功能:
def print_twice_str():
print_twice(str)
do_four(print_twice_str)
或者你可以内联做同样的事情:
do_four(lambda: print_twice(str))
或者您可以使用高阶函数partial
为您执行此操作:
from functools import partial
do_four(partial(print_twice, str))
partial
的文档有一个很好的解释:
partial()
用于部分函数应用程序,它“冻结”函数的参数和/或关键字的某些部分,从而产生具有简化签名的新对象。例如,partial()
可用于创建一个行为类似于int()
函数的调用,其中 base 参数默认为两个:[snip]basetwo = partial(int, base=2)
*如果您正在考虑“但我没有返回任何内容,那么None
来自哪里?”:每个函数总是在Python中返回一个值。如果您没有告诉它返回什么,它将返回None
。
答案 1 :(得分:3)
第do_four(print_twice(str))
行在传递之前首先计算括号中的表达式。由于print_twice没有返回任何内容,因此假设None
,并且它会被传递。
答案 2 :(得分:2)
现在print_twice
正在返回None
,这最终会作为参数传递给do_four
。换句话说,您传递函数调用的结果而不是函数调用本身。
相反,您希望将该函数调用包装在lamda函数中,如下所示:
do_four(lambda: print_twice(str))
这会将实际的函数调用作为参数传递,而不是调用函数并传递结果。