打印目标:
>>> 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