我有一个与程序行为改变有关的问题,缺少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))
Run Code Online (Sandbox Code Playgroud)
结果: 计数为4
如果我修改上面的方法,使最后一个语句不包含'return'语句,我得到的结果是'None'.
def count(x,acc=0):
if x==0:
return acc
count(x/10,acc+1)
print "Count is %s" %(count(1234))
Run Code Online (Sandbox Code Playgroud)
结果:计数为无
(我使用的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"
Run Code Online (Sandbox Code Playgroud)
结果:计数为:4
(我在代码块上面运行的Perl版本是:5.14.4和5.8.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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
159 次 |
| 最近记录: |