在这个示例代码中,使用了哪种Python习惯用法来调用函数?

在这个示例代码中,使用了哪种Python习惯用法来调用函数?,python,Python,我试图弄清楚,在接下来的几行中使用了哪种Python习语 state = state0 while state: state = state() 我不明白为什么这里是state0而不是state0()?这条线是什么 state = state() 你在干什么?为什么没有state0() Python允许变量作为函数引用。在您的示例中发生的实际上是一个较长版本的。首先,函数state0被分配到state。由于没有括号,Python不会调用函数,而是将函数分配给变量 示例中的whil

我试图弄清楚,在接下来的几行中使用了哪种Python习语

state = state0

while state:
    state = state()
我不明白为什么这里是state0而不是state0()?这条线是什么

state = state() 
你在干什么?为什么没有
state0()


Python允许变量作为函数引用。在您的示例中发生的实际上是一个较长版本的。首先,函数
state0
被分配到
state
。由于没有括号,Python不会调用函数,而是将函数分配给变量


示例中的
while
循环仅检查状态是否为未定义为false的任何内容(即not
None
、空列表等)。在循环的每次迭代中,变量
state
通过调用之前分配给它的函数来分配一个新函数,直到到达
state2
返回
None
的点,该点在
循环时中断

Python允许变量作为函数引用。在您的示例中发生的实际上是一个较长版本的。首先,函数
state0
被分配到
state
。由于没有括号,Python不会调用函数,而是将函数分配给变量


示例中的
while
循环仅检查状态是否为未定义为false的任何内容(即not
None
、空列表等)。在循环的每次迭代中,变量
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
函数。然后在循环中调用
状态
,并使用返回值更新它,返回值也是一个函数。所以每次你打电话给下一个傅