S. *_*diz 4 python parameters function
我有这个问题:
cons(a, b)构建一对,并且car(pair)和cdr(pair)返回对的第一和最后一个元素。例如,car(cons(3, 4))收益3和cdr(cons(3, 4))回报4。鉴于此缺点的实现:
Run Code Online (Sandbox Code Playgroud)def cons(a, b): def pair(f): return f(a, b) return pair实施
car和cdr。
我没有功能。
它具有一个内部函数,并在返回中调用另一个函数。据我了解,内部功能是这些功能应取决于它们上面的功能。在这种情况下cons(..)。
但是该函数未使用a或b。为何有该功能f?任务是实现car和cdr,并且f应该给出功能。
那么有人可以向我解释这个功能吗?我该如何开始这项任务?
Mar*_*ers 11
首先:Python函数对象是一流的对象。一条def语句会生成一个新的函数对象,您可以使用函数名称来检索该对象:
>>> def foo():
... return 'foo was called'
...
>>> foo
<function foo at 0x11b3d8ae8>
Run Code Online (Sandbox Code Playgroud)
这意味着您也可以将该对象分配给其他名称,并且可以将它们作为参数传递给函数调用。之后,您可以通过添加(...)到引用来调用函数对象:
>>> bar = foo
>>> bar()
'foo was called'
Run Code Online (Sandbox Code Playgroud)
函数名称在当前名称空间中分配给它。在模块中,这是全局变量,但是在诸如之类的函数中cons,该名称被添加为本地名称。return pair在cons函数然后返回功能对象pair给调用者。
并且函数参数(例如f和a和)b也是变量;如果将函数对象作为参数传递,parameter_name(...)则将调用paramater_name并传递...零件中的任何参数。f(a, b)呼叫f并传入a和b。
下一个要了解的项目是闭包;闭包是附加到函数对象上的额外名称空间,用于来自周围范围的变量。
在下面的示例中,spam是bar函数关闭中的名称:
>>> def foo():
... spam = 'Vikings'
... def bar():
... return spam
... return bar
...
>>> foo()
<function foo.<locals>.bar at 0x11b44bf28>
>>> foo()()
'Vikings'
Run Code Online (Sandbox Code Playgroud)
调用foo()返回一个新的函数对象;内的bar()功能foo()。调用返回的函数对象产生'Vikings',函数中spam变量的值foo。如何bar()获得这些信息?通过关闭:
>>> foo().__closure__
(<cell at 0x11b3c05b8: str object at 0x11b469180>,)
>>> foo().__closure__[0].cell_contents
'Vikings'
Run Code Online (Sandbox Code Playgroud)
因此,嵌套函数可以通过闭包访问周围范围的名称。(注意:不是在闭包中存储的值,而是变量。该变量可以随时间变化,就像以后访问该名称的其他变量将反映新值;如果spam以后更改,则bar()再次调用将返回新值)。
现在给你的函数:cons()创建一个内部函数pair(),并pair()先后获得了参数a,并b通过其关闭:
>>> def cons(a, b):
... def pair(f):
... return f(a, b)
... return pair
...
>>> cons(42, 81)
<function cons.<locals>.pair at 0x11b46f048>
>>> pair_42_81 = cons(42, 81)
>>> pair_42_81.__closure__
(<cell at 0x11b3c02b8: int object at 0x10f59a750>, <cell at 0x11b3c05b8: int object at 0x10f59ac30>)
>>> pair_42_81.__closure__[0].cell_contents
42
>>> pair_42_81.__closure__[1].cell_contents
81
Run Code Online (Sandbox Code Playgroud)
该pair()功能需要一个参数f,并调用该参数,传递a和b。让我们看看当我们通过时会发生什么print。
print 也是一个函数,它是一个您可以调用的对象,并且将参数写入控制台,中间有空格:
>>> print
<built-in function print>
>>> print('arg1', 'arg2')
arg1 arg2
Run Code Online (Sandbox Code Playgroud)
如果将其传递给返回的pair()函数,则cons()可以看到f(a, b)它的作用:
>>> pair_42_81(print)
42 81
Run Code Online (Sandbox Code Playgroud)
print传递给pair(),分配给f,并且与f(a, b)完全相同print(a, b)。
我们可以看到它print()被调用,因为这些值已写到控制台中。但是您也可以创建一个返回新值的函数。假设您有一个将两个数字相加并返回该值的函数:
>>> def add(first, second):
... return first + second
...
>>> add(42, 81)
123
>>> pair_42_81(add)
123
Run Code Online (Sandbox Code Playgroud)
我们可以直接调用该函数并123返回它,也可以pair_42_81()为我们完成该操作,然后将相同的结果返回给我们。简单!
所有这些都是有效的,因为函数是对象,可以像其他变量一样传递,并且因为pair_42_81has a = 42和c = 81存储在闭包中,并将使用那些函数来调用f带有这两个参数的给定对象。
接下来是cdr()和car(),它们将返回一对中的第一个或最后一个元素。如果cons(a, b)产生pair(f)返回f(a, b),则cdr()并且car()必须每个创建一个函数传递给pair()该函数来提取a或b。
因此,建立在每个嵌套函数,并有cdr()和car()调用pair()与该功能。嵌套函数完成选择a或的工作b,并返回该值。然后将调用结果返回给外界:
def car(pair):
def return_first(a, b):
return a
return pair(return_first)
def cdr(pair):
def return_last(a, b):
return b
return pair(return_last)
Run Code Online (Sandbox Code Playgroud)
pair(return_first)电话return_first(a, b),a被返回,car()可以返回给调用者:
>>> car(cons(42, 81))
42
Run Code Online (Sandbox Code Playgroud)
与相同pair(return_last),仅现在b返回:
>>> cdr(cons(42, 81))
81
Run Code Online (Sandbox Code Playgroud)
您可能对这些操作的背景感兴趣;car,cdr并且cons来自LISP,其中LISP cons a b 构造了一个具有两个指针的单元(解释名称),并且car(意味着创建LISP的IBM 704指令集中的寄存器编号的地址部分的地址内容)和cdr(意味着减量部分的内容) (以704语言表示的注册号码)(例如,该单元格的第一部分和其余部分)。请参阅有关名称的Wikipedia文章。
cons是一个函数,它接受两个参数,a并且b返回一个函数pair。
该函数pair采用一个函数f作为参数,该函数消耗两个参数。
def cons(a, b):
def pair(f):
return f(a, b)
return pair
f = lambda n, m: n**2 + m**3
car = lambda n, m: n
cdr = lambda n, m: m
print(cons(2, 3)(f))
print(cons(2, 3)(car))
print(cons(2, 3)(cdr))
Run Code Online (Sandbox Code Playgroud)
f回报31 = 2**2 + 3**3
请注意如何cons使用两次括号(...)- 一次用于其自身的调用,另一次用于返回的函数调用。
请注意此答案以便能够致电car(cons(2, 3))。您可能还对为什么程序要使用闭包感兴趣?