免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 9578 | 回复: 12
打印 上一主题 下一主题

由用错PYTHON的递归想到的 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-12-28 23:29 |只看该作者 |倒序浏览
之前因为原来养成不良编码风格的原因, 初学PYTHON想试试它的递归, 就用最简单的阶乘来试, 结果出了问题, 还以为PYTHON的递归有什么特别的东西, 今天再试了一试, 终于发现为什么错了, 把过程发出来, 让某些有同样经历的人(也许再没人会发生这种情况)引以为JIAN:

首先看PERL里面求阶乘的例子:

  1. sub fact{
  2.   my $n = $_[0];
  3.   if($n>1) {                #可写为:
  4.     $n = $n * fact($n-1) ;  #  $n *= fact($n-1) if $n > 1;
  5.   }else{                    #
  6.     return $n;              #  return $n;
  7.   }                         #但以前受C的影响, 所以那样写了
  8. }

  9. print fact(50);
复制代码

这样成功了, 在IF中不用返回, 因为它一定会返回值!

下面用PYTHON依葫芦画瓢来写一个最简单的例子:

  1. -----------------------------------------------------
  2. >>> def fact(n):
  3. ...   if n>1:
  4. ...     n = n* fact(n-1);
  5. ...   else:
  6. ...     return n
  7. ...
  8. >>> fact(10)
  9. Traceback (most recent call last):
  10.   File "<stdin>", line 1, in <module>
  11.   File "<stdin>", line 3, in fact
  12.   File "<stdin>", line 3, in fact
  13.   File "<stdin>", line 3, in fact
  14.   File "<stdin>", line 3, in fact
  15.   File "<stdin>", line 3, in fact
  16.   File "<stdin>", line 3, in fact
  17.   File "<stdin>", line 3, in fact
  18.   File "<stdin>", line 3, in fact
  19. TypeError: unsupported operand type(s) for *: 'int' and 'NoneType'
  20. -----------------------------------------------------
复制代码

HOHO!出错了, 说fact是NONE类型的, 不能返回给INT类型
WA-KAO! 我明明是返回了值的呀, 怎么会说是NONE型呢?
于是我脑子一转: 莫非是每个逻辑路都要有返回值? 于是修改:

  1. -----------------------------------------------------
  2. >>> def fact(n):
  3. ...   if n>1:
  4. ...     n = n* fact(n-1);
  5. ...     return n
  6. ...   else:
  7. ...     return n
  8. ...
  9. >>> fact(5)
  10. 120
  11. -----------------------------------------------------
复制代码

OK! 成功了, 于是猜想PYTHON是编译时就检查它每条逻辑路的返回值,
如果发现某条逻辑分支没返回, 而最后也没返回的话, 就是NONE型.
到底是不是呢? 为了证实, 我再改进一下, 不在分支返回,
而在最后返回, 试试看:

  1. -----------------------------------------------------
  2. >>> def fact(n):
  3. ...   if n>1:
  4. ...     n = n * fact(n-1)
  5. ...   return n
  6. ...
  7. >>> fact(5)
  8. 120
  9. -----------------------------------------------------
复制代码

YAHOO! 明白了, 真的是PYTHON在编译时会看是不是绝
对有返回, 如果出现意外会不能返回的话就说你是NONE型.
看来MUTI-RETURN(多个RETURN分支)的编程风格真的不好!
JAVA里反对MUTI-RETURN, 现在PYTHON也不喜欢MUTI-RETURN!
那以后写程序最好还是在最后返回算了!

论坛徽章:
0
2 [报告]
发表于 2006-12-29 01:22 |只看该作者
你这样一个分支里面不return东西,c里面也不能通过的阿。只能说perl的bug而已

论坛徽章:
0
3 [报告]
发表于 2006-12-29 02:17 |只看该作者
哈哈,五分钟前我也有你这样的问题
我的代码是:
def fib(n):
        if n > 1:
                print n * fib(n - 1)#这里的print 应该是return
        else:
                print 'End of line'
                return 1
然后就出现一大堆报错,后来才找到原因,怪不得在书里一直强调某代码的返回的是什么~

论坛徽章:
0
4 [报告]
发表于 2006-12-29 08:45 |只看该作者
这是不同语言的设计风格,python讲究明显比隐晦要好,所以许多东西需要显示的处理。

论坛徽章:
0
5 [报告]
发表于 2008-03-04 16:44 |只看该作者
你的程序本来就写的有问题,这种分支结构拿到C语言里也不是没有返回值吗?起码不会返回正确的值!

论坛徽章:
0
6 [报告]
发表于 2008-03-09 21:45 |只看该作者
楼主, 0 的阶乘是多少啊

[ 本帖最后由 libin1983 于 2008-3-10 09:55 编辑 ]

论坛徽章:
0
7 [报告]
发表于 2008-03-11 10:22 |只看该作者
LZ的程序,0的阶乘返回还是0。。
est 该用户已被删除
8 [报告]
发表于 2008-03-13 00:07 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
9 [报告]
发表于 2008-03-13 04:38 |只看该作者
原帖由 wannachan 于 2006-12-28 07:29 发表
之前因为原来养成不良编码风格的原因, 初学PYTHON想试试它的递归, 就用最简单的阶乘来试, 结果出了问题, 还以为PYTHON的递归有什么特别的东西, 今天再试了一试, 终于发现为什么错了, 把过程发出来, 让某些有同样 ...


如果没有return,perl会返回最后一个expression的值,就是if里面的n*fact(n-1),因此是对的;python不会。

论坛徽章:
0
10 [报告]
发表于 2008-04-13 23:24 |只看该作者

不用return的递归

nodelocation={};
lines=[];
nodes=[];
layernodes=[];
for i in range(0,10):
    lines.append([]);

def recursive_construction(n,label='',label_remain_char=[],location={},diameter=0):
    loc={};
    if len(label_remain_char) > 3 :
        for i in range(0,len(label_remain_char)):
            sinx=math.sin(i*2*math.pi/n);
            cosx=math.cos(i*2*math.pi/n);
            if sinx>1 or sinx < -1 or (sinx < 1e-10 and sinx > -1e-10):
                sinx=0;
            if cosx>1 or cosx < -1 or (cosx < 1e-10 and cosx > -1e-10):
                cosx=0;
            loc['x']=location['x']+diameter*cosx;loc['y']=location['y']+diameter*sinx;
            label_remain=label_remain_char[:];
            popitem=label_remain.pop(i);
            recursive_construction(n-1,popitem+label,label_remain,loc,diameter/3);

        #deal with the lines of the current layer
    elif len(label_remain_char) == 3 :
        #deal with the hex-circle
        diameter=2;
        hexlabel=''.join('%s'%j for j in label_remain_char);
        for i in range(0,6):
            sinx=math.sin(i*2*math.pi/6);
            cosx=math.cos(i*2*math.pi/6);
            if sinx>1 or sinx < -1 or (sinx < 1e-10 and sinx > -1e-10):
                sinx=0;
            if cosx>1 or cosx < -1 or (cosx < 1e-10 and cosx > -1e-10):
                cosx=0;
            x=location['x']+diameter*cosx;y=location['y']+diameter*sinx;
            nodelocation['%s'%(hexlabel+label)]={'x','y':y};
            nodes.append('%s'%(hexlabel+label));
            hexlabelold=hexlabel;
            if i%2==0 :
                hexlabel=''.join(j for j in hexlabel[-2:-4:-1])+'%s'%hexlabel[-1];
            else:
                hexlabel=''.join(j for j in hexlabel[-1:-4:-1]);
            lines[0].append((hexlabelold+label,hexlabel+label));
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP