简体   繁体   English

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

[英]Defining function with function object passed in as argument

I'm using the internet to teach myself something useful like python. 我正在使用互联网自学一些有用的内容,例如python。 The resources I've been using so far 'Think python' by Downey and 'Learning Python' by Lutz. 到目前为止,我一直在使用Downey的“ Think python”和Lutz的“ Learning Python”资源。 I was first introduced to python the Udacity programme on computer science, and have been teaching myself from here on in. I'm a coding neophyte and this is the first language I've attempted to learn. 我是最初接触python的Udacity计算机科学程序的入门者,并且一直从这里开始自学。我是一名编码新手,这是我尝试学习的第一门语言。

My problem, is one posed by Downey in 'think python' and is defining a function that takes a function object as one of its arguments along with the number n. 我的问题是Downey在“ think python”中提出的,并且正在定义一个函数,该函数将函数对象作为参数之一以及数字n。

It was introduced in the recursive programming chapter and has been giving me kittens. 它是在递归编程章节中介绍的,一直给我小猫。

My code so far: 到目前为止,我的代码:

    def print_string(s):
        print (s)
        return

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

now I've been trying this with a simple predefined print function called print_ string that takes argument(s). 现在,我一直在尝试使用名为print_ string的简单预定义打印函数,该函数接受参数。

I save the script in a file called recursive.py and run it in IDLE then after it's run i call do_n with the following do_n(print_string('test'), 6) 我将脚本保存在一个名为recursive.py的文件中,并在IDLE中运行,然后在运行后,使用以下do_n(print_string('test'),6)调用do_n。

I expect to print the sample string 'test' 6 times but it only prints once. 我希望将示例字符串“ test”打印6次,但仅打印一次。 There appears to be no recursion. 似乎没有递归。

What am i doing wrong? 我究竟做错了什么? Any help would be appreciated because i can't really afford to sign up with Udacity or anything else this is just me & the internet vs python. 任何帮助将不胜感激,因为我真的负担不起Udacity或其他任何东西的注册,这仅仅是我&互联网vs python。 TIA TIA

Hi this is the final code that i ended up with that actually worked. 嗨,这是我最终实际使用的最终代码。

    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)

The two print calls 'been here' and type(f) were put in to try and understand what was going on with the program and don't need to be there, but i like the reminder of the leap i've made - so they're staying in. 插入了两个“ been here”和type(f)的打印调用,以尝试了解程序发生了什么,并且不需要在那里,但我想提醒自己已经取得了飞跃-因此他们待在里面。

I think you are very nearly there. 我想你已经很近了。 I think the problem is with your call to f in your method. 我认为问题出在您对方法中的f的调用上。 Don't forget - you have passed in a function as f , not a function call . 别忘了-您将函数传递为f ,而不是函数调用 So, when you have f in your do_n function, it does nothing. 因此,当do_n函数中包含f时,它什么也不做。 If you did f() it would actually call f (with no arguments, which may or may not be allowed) and, possibly better, if you did f(n) it should call print_string with n as the argument. 如果执行了f() ,它将实际上调用f(不带任何参数,这可能会或不允许),并且如果执行f(n)则可能会调用带有n作为参数的print_string I mocked up a little demo to get you going: 我模拟了一个小演示让您开始:

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)

* EDIT * *编辑*

In response to OP clarification in edit. 为了响应OP在编辑中的澄清。 The original code was as per the original post, but called with the line 原始代码与原始帖子相同,但用以下行调用

do_n(print_string('test'),6)

The problem with this is that the print_string() function is being before you ever enter do_n . 问题在于,在您输入do_n之前,就存在print_string()函数。 As the print_string() function simply prints what it's given (I assume) and returns nothing - you're actually passing None into the do_n function. 由于print_string()函数只是打印给出的内容(我假设)并且不返回任何内容-您实际上是将None传递给do_n函数。

As an aside and to convince yourself that the print_string is being evaluated before do_n is ever called - try making a single change to your original to say do_n ,并说服自己在do_n之前已对print_string进行了评估-尝试对原始do_n进行一次更改以说

do_n(print_string('test'),0)

You might expect to see nothing, but in fact you will see the output test as the print_string is still called. 您可能希望什么都看不到,但是实际上您会看到输出test因为仍然调用print_string。

Solution

To pass a function into another function, you pass its name, but don't follow it with any brackets or arguments. 要将一个函数传递给另一个函数,请传递其名称,但不要在其后加上任何方括号或参数。 In that way, you are passing the function object, not the result of calling that function. 这样,您传递的是函数对象,而不是调用该函数的结果。

You actually call the function (or indeed pass it on to another function) from within the receiving function where you want it to do something. 您实际上是从接收函数内部调用该函数(或实际上将其传递给另一个函数)。 My example code above still stands. 我上面的示例代码仍然存在。 Note - I pass in print_string with no brackets or arguments. 注意-我传入的print_string没有括号或参数。

This is a powerful technique - it might take a little thinking to get your head round, but it's worthwhile doing so. 这是一项强大的技术-可能需要花点时间思考,但这样做是值得的。 As a rule of thumb - if you see a function name that isn't followed by any brackets, it's being passed as a function object. 根据经验,如果您看到函数名称后没有方括号,则会将其作为函数对象传递。 If it's followed by brackets, it's being evaluated at that point. 如果后面有方括号,则表示正在对此进行评估。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM