打印目标:
>>> runfile('E:/桌面/代码池/untitled0.py', wdir='E:/桌面/代码池') num:11 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 1 6 15 20 15 6 1 1 7 21 35 35 21 7 1 1 8 28 56 70 56 28 8 1 1 9 36 84 126 126 84 36 9 1 1 10 45 120 210 252 210 120 45 10 1
代码:
def triangle(num): triangle=[[1]] for i in range(2,num+1): triangle.append([1]*i) for j in range(1,i-1): triangle[i-1][j]=triangle[i-2][j]+triangle[i-2][j-1] return triangle def printtriangle(triangle,width): column=len(triangle[-1])*width for sublist in triangle: result=[] for contents in sublist: result.append('{0:^{1}}'.format(str(contents),width)) print('{0:^{1}}'.format(''.join(result),column)) if __name__=='__main__': num=int(input('num:')) triangle=triangle(num) width=len(str(triangle[-1][len(triangle[-1])//2]))+3 printtriangle(triangle,width)
第一步,获取由杨辉三角各行所构成的表格
实现方法有很多,这里详细介绍一种,其余几种方法会在下一篇文章中介绍。先来看这样一段代码:
def triangle(num):#num是打印杨辉三角的行数 triangle=[] sublist=[] for i in range(1,num+1): sublist.append(1) for j in range(1,i-1): sublist[-j-1]=sublist[-j-1]+sublist[-j-2]#从倒数第二个元素开始向前处理,直到正数第二个元素。 triangle.append(sublist) return triangle除了中间递归看着比较累外,其他地方似乎没什么问题。运行一下看看:
>>> runfile('E:/桌面/代码池/untitled0.py', wdir='E:/桌面/代码池') num:5 1 4 6 4 1 1 4 6 4 1 1 4 6 4 1 1 4 6 4 1 1 4 6 4 1
怎么会这样呢?这里隐藏着python中的一个天坑:
python不允许程序员选择采用传值还是传引用。Python参数传递采用的肯定是“传对象引用”的方式。实际上,这种方式相当于传值和传引用的一种综合。如果函数收到的是一个可变对象(比如字典或者列表)的引用,就能修改对象的原始值——相当于通过“传引用”来传递对象。
重点是那句“能修改对象的原始值”。由于传入的sublist是可变对象,因此加入triangle的仅仅是sublist的引用。虽然我们已经一步步将sublist加到了triangle里面,但每一步对sublist进行append操作,都将原有的sublist进行了改变。我们本以为的实现方式是这样的:
但代码实际上在python内部实现的过程是这样的:
为了更好的理解“传值”与“传引用”,我们看这样一段代码:
triangle=[] sublist=1 for i in range(1,10): sublist+=1 triangle.append(sublist) print(sublist)
在python内部实现的方式是怎样的呢?
我们可以看到,对于不可变元素,python采取的就是“传值”的方式。
知道了问题所在,该如何去修改呢?我们只需要在sublist加入triangle之前,使sublist指向一个新的列表对象。
sublist=sublist+[1] #替代sublist.append(1)
改动完成,打印一下看看:
>>> runfile('E:/桌面/代码池/untitled1.py', wdir='E:/桌面/代码池') [[1], [1, 1], [1, 2, 1], [1, 3, 3, 1], [1, 4, 6, 4, 1], [1, 5, 10, 10, 5, 1], [1, 6, 15, 20, 15, 6, 1], [1, 7, 21, 35, 35, 21, 7, 1], [1, 8, 28, 56, 70, 56, 28, 8, 1]]
嗯,貌似还不错,获得了杨辉三角各行组成的列表,下面的任务就是格式化打印了。全部代码如下先看代码:
def printtriangle(triangle,width): column=len(triangle[-1])*width for sublist in triangle: result=[] for contents in sublist: result.append('{0:^{1}}'.format(str(contents),width)) print('{0:^{1}}'.format(''.join(result),column)) if __name__=='__main__': num=int(input('num:')) triangle=triangle(num) width=len(str(triangle[-1][len(triangle[-1])//2]))+3 printtriangle(triangle,width)
重点解释一下这两行:
result.append('{0:^{1}}'.format(str(contents),width)) #控制各行数字间距 print('{0:^{1}}'.format(''.join(result),column)) #控制缩进第一行用来控制同行数字的间距,具体而言:str(contents)占据的总宽度为width,不足的 在两边用空格补齐。这样做的结果是每一个加入result的数字两边都有空格。
<pre name="code" class="python" style="font-size: 11.8518514633179px;">x=['1','2']=> x=[' 1 ',' 2 ']#效果类似这样
第二行同理:‘’.join()占据总宽度为‘盒子’总宽度column(而column又由行数决定),并用空格在两边补齐空位。
如果不想用短线补齐空位呢?只需要这样修改:
print('{0:-^{1}}'.format(''.join(result),column)) #控制缩进
好了,输入num=10,看看效果:
>>> runfile('E:/桌面/代码池/untitled0.py', wdir='E:/桌面/代码池') 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 1 6 15 20 15 6 1 1 7 21 35 35 21 7 1 1 8 28 56 70 56 28 8 1 1 9 36 84 126 126 84 36 9 1
到这里基本就大功告成了,感兴趣的朋友还可以看看其它四种实现方法(尤其,后面两种):
def gettriangle(num):#1 triangle=[] sublist=[] for i in range(1,num+1): sublist=sublist+[1]#思考:为什么不能写成sublist.append(1) for j in range(1,i-1): sublist[-j-1]=sublist[-j-1]+sublist[-j-2] triangle.append(sublist) return triangle
</pre><pre name="code" class="python">
</pre><pre name="code" class="python">def gettriangle(num):#2 triangle=[[1]] sublist=[1] for i in range(1,num): sublist.append(1) sublistcopy=sublist[:] for j in range(1,i): sublistcopy[j]=sublist[j]+sublist[j-1] sublist=sublistcopy[:] triangle.append(sublistcopy)
def gettriangle(num):#3 triangle=[[1]] sublist=[1] for i in range(1,num): sublist=[1]+[sublist[i]+sublist[i+1] for i in range(len(sublist)-1)]+[1] triangle.append(sublist) return triangle
def gettriangle(num):#4 triangle=[[1]] sublist=[1] for i in range(1,num): sublist=[sum(i) for i in zip([0]+sublist,sublist+[0])] triangle.append(sublist) return triangle