编写一个不带参数的函数,该函数返回两个函数:prepend和get。

huangapple go评论64阅读模式
英文:

Write a function that takes in no arguments and returns two functions, prepend and get,

问题

以下是翻译好的内容:

编写一个不接受任何参数的函数,该函数返回两个函数:prepend和get,分别表示“在列表前添加元素”和“获取第i个元素”的操作。请不要使用任何Python内置的数据结构,如列表或字典。你不一定需要使用所有的代码行。

def nonlocalist():
    get = lambda x: "Index out of range!"
    def prepend(value):
        nonlocal get
        f = get
        def get(i):
            if i == 0:
                return value
            return f(i - 1)
    return prepend, lambda x: get(x)

有人可以帮忙解释一下这些代码是如何工作的吗?我从一开始就不知道如何编写它。

英文:

Write a function that takes in no arguments and returns two functions, prepend and
get, which represent the “add to front of list” and “get the ith item” operations,
respectively. Do not use any python built-in data structures like lists or dictionaries.
You do not necessarily need to use all the lines

def nonlocalist():
    get = lambda x: "Index out of range!"
    def prepend(value):
        nonlocal get
        f = get
        def get(i):
            if i == 0:
                return value
            return f(i - 1)
    return prepend, lambda x: get(x)

can someone help explain how these codes work, i have no idea from the beginning how to write it.

答案1

得分: 3

简而言之,这个代码通过在闭包中存储数据,并使用递归来检索数据。闭包的简要介绍如下:

def foo(value):
    def bar():
        print(value)

    return bar

b = foo(42)
b()  # 输出 42

这里的value被“闭合”。这意味着即使foo的执行已经结束,变量value应该已经超出了作用域并被垃圾回收,但由于bar引用它,它仍然被保留,并且实际上在调用bar时可以访问。

你的链表代码利用了这个原理,在越来越嵌套的作用域中存储值,并使用递归遍历作用域并检索值。

下面是这个过程的可视化示例:

编写一个不带参数的函数,该函数返回两个函数:prepend和get。

你可以在这里自己尝试运行它:这里


调用nonlocalist时,你会得到两个函数:prepend和一个调用“最新版本”的get的函数。

prepend总是执行以下操作:

  1. 接受一个value参数。
  2. 将当前版本的get存储在f中。
  3. 用一个新的函数覆盖get,该函数要么:
    • 返回value(就像上面闭包示例中演示的那样),或者
    • 调用先前版本的get(现在称为f),该版本已经闭合了先前的value

当你调用nonlocalist给你的第二个“getter”函数时,它会:

  1. 查找当前版本的get并调用它,这个函数
  2. 返回它所闭合的value或其先前版本的结果。
英文:

In a nutshell, this works by storing data in closures, and using recursion to retrieve them. As a very short primer on closures:

def foo(value):
    def bar():
        print(value)

    return bar

b = foo(42)
b()  # prints 42

The value here is being "closed over". This means even though the execution of foo has already ended and the variable value should have gone out of scope and been garbage collected, since bar refers to it, it is still kept around and is in fact accessible to bar when called.

Your linked list code uses this principle to store values in more and more nested scopes, and uses recursion to traverse back up the scopes and retrieve them.

Here's a visualisation of this abomination in action:

编写一个不带参数的函数,该函数返回两个函数:prepend和get。

You can play around with it yourself here.


When calling nonlocalist, you get two functions back: prepend, and a function that calls the "latest version" of get.

prepend always does the same thing:

  1. Take a value argument.
  2. Store the current version of get in f.
  3. Overwrite get with a new function which either:
    • returns value (as demonstrated in the closure example above), or
    • calls the previous version of get (now called f), which has the previous value closed over

When you call the second "getter" function that nonlocalist gave you, it:

  1. Looks up the current version of get and calls it, which
  2. returns the value it has closed over or the result of its previous version.

huangapple
  • 本文由 发表于 2023年7月27日 17:36:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/76778402.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定