在这个示例代码中,使用了哪种Python习惯用法来调用函数?
我试图弄清楚,在接下来的几行中使用了哪种Python习语在这个示例代码中,使用了哪种Python习惯用法来调用函数?,python,Python,我试图弄清楚,在接下来的几行中使用了哪种Python习语 state = state0 while state: state = state() 我不明白为什么这里是state0而不是state0()?这条线是什么 state = state() 你在干什么?为什么没有state0() Python允许变量作为函数引用。在您的示例中发生的实际上是一个较长版本的。首先,函数state0被分配到state。由于没有括号,Python不会调用函数,而是将函数分配给变量 示例中的whil
state = state0
while state:
state = state()
我不明白为什么这里是state0而不是state0()?这条线是什么
state = state()
你在干什么?为什么没有state0()
Python允许变量作为函数引用。在您的示例中发生的实际上是一个较长版本的。首先,函数
state0
被分配到state
。由于没有括号,Python不会调用函数,而是将函数分配给变量
示例中的
while
循环仅检查状态是否为未定义为false的任何内容(即notNone
、空列表等)。在循环的每次迭代中,变量state
通过调用之前分配给它的函数来分配一个新函数,直到到达state2
返回None
的点,该点在循环时中断。Python允许变量作为函数引用。在您的示例中发生的实际上是一个较长版本的。首先,函数state0
被分配到state
。由于没有括号,Python不会调用函数,而是将函数分配给变量
示例中的while
循环仅检查状态是否为未定义为false的任何内容(即notNone
、空列表等)。在循环的每次迭代中,变量state
通过调用之前分配给它的函数分配一个新函数,直到到达state2
返回None
的点,该点在循环时中断。如其他人所述,您可以将函数分配给变量,然后根据需要执行它
下面是一个简单的示例,说明如何使用它(尽管有点人为)
假设您确实想要编写一个计算阶乘的递归函数。很简单,你可以写这样的东西
def fact(n, res=1):
return res if n==0 else fact(n-1, res=res*n)
fact(5)()()()()()
问题是,如果您尝试在大n
上执行此操作,比如10000,这将导致调用堆栈溢出,您将收到
RecursionError: maximum recursion depth exceeded in comparison
解决这个问题的一种方法是返回一个函数而不是结果,然后自己执行它
def fact(n, res=1):
return res if n==0 else lambda: fact(n-1, res=res*n)
现在你可以这样称呼它
def fact(n, res=1):
return res if n==0 else fact(n-1, res=res*n)
fact(5)()()()()()
这将为您提供正确的结果。优点是您不再受调用堆栈大小的限制。显然,您不想编写所有这些大括号,这样您就可以编写一个循环来为您完成。该循环将检查结果是否可调用,并根据该结果执行函数或返回结果
def loop(func, n):
res = func(n)
while hasattr(res, "__call__"):
res = res()
return res
现在,您可以使用fact
函数将n
设置为10000,而无需调用
loop(fact, 10000)
正如其他人所提到的,您可以将函数分配给变量,然后根据需要执行它
下面是一个简单的示例,说明如何使用它(尽管有点人为)
假设您确实想要编写一个计算阶乘的递归函数。很简单,你可以写这样的东西
def fact(n, res=1):
return res if n==0 else fact(n-1, res=res*n)
fact(5)()()()()()
问题是,如果您尝试在大n
上执行此操作,比如10000,这将导致调用堆栈溢出,您将收到
RecursionError: maximum recursion depth exceeded in comparison
解决这个问题的一种方法是返回一个函数而不是结果,然后自己执行它
def fact(n, res=1):
return res if n==0 else lambda: fact(n-1, res=res*n)
现在你可以这样称呼它
def fact(n, res=1):
return res if n==0 else fact(n-1, res=res*n)
fact(5)()()()()()
这将为您提供正确的结果。优点是您不再受调用堆栈大小的限制。显然,您不想编写所有这些大括号,这样您就可以编写一个循环来为您完成。该循环将检查结果是否可调用,并根据该结果执行函数或返回结果
def loop(func, n):
res = func(n)
while hasattr(res, "__call__"):
res = res()
return res
现在,您可以使用fact
函数将n
设置为10000,而无需调用
loop(fact, 10000)
函数是对象。您可以看到您的函数实际上返回其他函数。因此,您最初将state
设置为state0
函数。然后在循环中调用状态
,并使用返回值更新它,返回值也是一个函数。因此,每次调用下一个函数直到返回None
,state=state0
时,不调用state0
;它使state
成为state0
的另一个名称。在循环内部,您反复调用某个函数(无论状态
引用什么),每个函数返回一个对下一个应该调用的函数的引用。正如我所说的,函数只是对象。使用它们的名称是引用对象。因此,您可以使用同一个函数对象分配多个变量。只有当您使用()
时,它实际上是在调用函数“调用带括号的函数”是多余的;括号是调用。如果没有括号,您只需要对对象进行引用。从语法上讲,foo()
无论foo
引用什么都是有效的,但如果foo
不可调用,则在运行时会出现TypeError
。好吧,我会尽量避免随机资源获取信息。尽量坚持官方文件,比如:。从此处:函数定义将函数名称与当前符号表中的函数对象相关联。解释器将该名称所指向的对象识别为用户定义的函数。其他名称也可以指向同一个函数对象,也可以用于访问FunctionAres对象。您可以看到您的函数实际上返回其他函数。因此,您最初将state
设置为state0
函数。然后在循环中调用状态
,并使用返回值更新它,返回值也是一个函数。所以每次你打电话给下一个傅