英文:
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
时可以访问。
你的链表代码利用了这个原理,在越来越嵌套的作用域中存储值,并使用递归遍历作用域并检索值。
下面是这个过程的可视化示例:
你可以在这里自己尝试运行它:这里。
调用nonlocalist
时,你会得到两个函数:prepend
和一个调用“最新版本”的get
的函数。
prepend
总是执行以下操作:
- 接受一个
value
参数。 - 将当前版本的
get
存储在f
中。 - 用一个新的函数覆盖
get
,该函数要么:- 返回
value
(就像上面闭包示例中演示的那样),或者 - 调用先前版本的
get
(现在称为f
),该版本已经闭合了先前的value
- 返回
当你调用nonlocalist
给你的第二个“getter”函数时,它会:
- 查找当前版本的
get
并调用它,这个函数 - 返回它所闭合的
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:
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:
- Take a
value
argument. - Store the current version of
get
inf
. - 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 calledf
), which has the previousvalue
closed over
- returns
When you call the second "getter" function that nonlocalist
gave you, it:
- Looks up the current version of
get
and calls it, which - returns the
value
it has closed over or the result of its previous version.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论