使用作为参数传入的函数对象定义函数

Defining function with function object passed in as argument

我正在使用互联网自学一些有用的东西,例如 python。到目前为止我一直在使用的资源是 Downey 的 'Think python' 和 Lutz 的 'Learning Python'。我第一次接触 python Udacity 计算机科学项目,并从现在开始自学。我是编码新手,这是我尝试学习的第一门语言。

我的问题是 Downey 在 'think python' 中提出的一个问题,它正在定义一个函数,该函数将函数对象作为其参数之一以及数字 n。

在递归编程章节介绍过,一直给我养小猫。

到目前为止我的代码:

    def print_string(s):
        print (s)
        return

    def do_n(f , n):
        if n <=0:
            return
        f
        do_n(f, n-1) 

现在我一直在尝试使用一个名为 print_string 的简单预定义打印函数,该函数接受参数。

我将脚本保存在一个名为 recursive.py 的文件中,并在 IDLE 中将其保存为 运行 然后在 运行 之后,我使用以下 do_n 调用 do_n (print_string('test'), 6)

我希望打印示例字符串 'test' 6 次,但它只打印一次。似乎没有递归。

我做错了什么?任何帮助将不胜感激,因为我真的负担不起注册 Udacity 或其他任何东西这只是我和互联网 vs python。 TIA

我想你快到了。我认为问题在于您在方法中调用 f 。别忘了 - 您传入的是 函数 作为 f,而不是 函数调用 。因此,当您在 do_n 函数中包含 f 时,它什么都不做。如果你做了 f() 它实际上会调用 f (没有参数,可能允许也可能不允许)而且,如果你做了 f(n) 它应该调用 print_stringn 作为参数。我模拟了一个小演示来帮助您:

def print_string(arg1=''):
    # mimicing your "pre-defined" function
    # Note I've put a default value in arg1 so that you
    # can call it without an argument to illustrate the priciple
    print(arg1)    

def do_n(f , n):
    if n <=0:
        return
    f('test')         # This is the line that was close, but not quite right
    do_n(f, n-1)

do_n(print_string,10)

* 编辑 *

回应编辑中的 OP 说明。原始代码与原始 post 相同,但使用行

调用
do_n(print_string('test'),6)

问题在于 print_string() 函数在您输入 do_n 之前就已存在。由于 print_string() 函数只是打印它给出的内容(我假设)而 returns 什么都没有 - 你实际上是将 None 传递给 do_n 函数。

顺便说一句,让自己相信 print_stringdo_n 被调用之前正在被评估 - 尝试对您的原始内容进行一次更改以说

do_n(print_string('test'),0)

您可能希望什么也看不到,但实际上您会看到输出 test,因为 print_string 仍在调用。

解决方案

要将一个函数传递给另一个函数,您需要传递它的名称,但不要在它后面跟任何括号或参数。这样,您传递的是函数对象,而不是调用该函数的结果。

您实际上是从接收函数中调用该函数(或确实将其传递给另一个函数),您希望它执行某些操作。我上面的示例代码仍然有效。注意 - 我传入的 print_string 没有括号或参数。

这是一项强大的技术 - 可能需要花点时间思考才能让您头脑清醒,但这样做是值得的。作为一个经验法则——如果你看到一个函数名后面没有任何括号,它被作为一个函数对象传递。如果它后面有方括号,那么它正在评估。

嗨,这是我最终得到的实际有效的最终代码。

    def print_string():
        print ('result')
        return
    def do_n(f, n):
        if n <=0:
            return
        print(type(f))
        f()
        print('been here')
        do_n(f, n-1) 

    do_n(print_string, 6)

两个 print 调用 'been here' 和 type(f) 是为了尝试理解程序正在发生的事情,不需要在那里,但我喜欢飞跃的提醒我做到了 - 所以他们会留下来。