我有一个与程序行为变化有关的问题 缺少 return 语句会导致python方法。
下面的 count 方法打印给定整数中的位数。 使用下面的代码块,我得到的结果为4,即 预期的结果。
def count(x,acc=0):
if x==0:
return acc
return count(x/10,acc+1)
print "Count is %s" %(count(1234))
结果: 计数为4
如果我修改上面的方法,那么最后一个语句不包含 'return'语句我得到的结果是'None'。
def count(x,acc=0):
if x==0:
return acc
count(x/10,acc+1)
print "Count is %s" %(count(1234))
结果:计数为无
(我使用的Python版本是:2.7.3)
由于Python不进行尾调用优化或是否涉及其他任何推理,是否会导致上述行为?
perl中的类似代码块(AFAIK不进行尾调用优化)提供 没有'return'的预期结果是最后一个声明的一部分。
sub counter {
my ($n,$acc) = @_;
return $acc if ($n==0);
counter(int($n/10), $acc+1);
}
print "Count is:" . counter(1234,0) ."\n"
结果:计数为:4
(我在代码块上面运行的Perl版本是:5.14.4和5.8.5)。
我的问题是:
答案 0 :(得分:5)
根本没有遗漏尾部优化。 Python中的函数需要显式关键字return
,否则假定它们返回None
。
我知道Ruby不会那样,它返回上次执行的表达式的值。使用Perl它必须是相同的。
这不是什么聪明,只是Python程序的行为方式:)
请参阅两个Python函数的反汇编。您可能会看到具有return
值的那个实际上如何调用该函数并将值返回到堆栈顶部。没有它的那个,看到在funciont调用之后有两个指令,它加载常量None
并返回它。
def count(x,acc=0):
if x==0:
return acc
return count(x/10,acc+1)
def count2(x,acc=0):
if x==0:
return acc
count(x/10,acc+1)
In [7]: import dis
In [8]: dis.dis(count)
2 0 LOAD_FAST 0 (x)
3 LOAD_CONST 1 (0)
6 COMPARE_OP 2 (==)
9 POP_JUMP_IF_FALSE 16
3 12 LOAD_FAST 1 (acc)
15 RETURN_VALUE
4 >> 16 LOAD_GLOBAL 0 (count)
19 LOAD_FAST 0 (x)
22 LOAD_CONST 2 (10)
25 BINARY_DIVIDE
26 LOAD_FAST 1 (acc)
29 LOAD_CONST 3 (1)
32 BINARY_ADD
33 CALL_FUNCTION 2
36 RETURN_VALUE
In [9]: dis.dis(count2)
2 0 LOAD_FAST 0 (x)
3 LOAD_CONST 1 (0)
6 COMPARE_OP 2 (==)
9 POP_JUMP_IF_FALSE 16
3 12 LOAD_FAST 1 (acc)
15 RETURN_VALUE
4 >> 16 LOAD_GLOBAL 0 (count)
19 LOAD_FAST 0 (x)
22 LOAD_CONST 2 (10)
25 BINARY_DIVIDE
26 LOAD_FAST 1 (acc)
29 LOAD_CONST 3 (1)
32 BINARY_ADD
33 CALL_FUNCTION 2
36 POP_TOP
37 LOAD_CONST 0 (None)
40 RETURN_VALUE
答案 1 :(得分:3)
没有return
,这是唯一一种在acc == 0
时返回内容的情况;对于您的count
递归方法的任何其他调用,您不会返回任何内容,因此收到None
。
与其他语言(scala,显然也是perl,可能是其他语言)不同,python默认情况下不返回最后一个语句,你必须明确地调用return
。
答案 2 :(得分:2)
尾部调用消除不会阻止Perl的语义(虽然没有Perl语义,你的尾部调用会少得多,因为每个函数都会以return;
隐式结束)。这纯粹是一种语言设计选择。 Perl和Python不同的原因是它们不是由同一个人设计的。
返回值的语法因语言选择而异。 Python的设计者选择了一个明确的return
语句。在QBasic中,您必须分配值以返回与该函数具有相同名称的变量。
答案 3 :(得分:0)
没有return
语句的Python函数返回值None
。
在这种情况下,您只会在x == 0
时返回一个值,因此会得到None
。有关详细信息,请查看Python教程:http://docs.python.org/2/tutorial/controlflow.html#defining-functions