*说明:杨辉三角形,又称贾宪三角形,帕斯卡三角形,是二项式系数在三角形中的一种几何排列。
实现方法生成器(generate),详见:廖雪峰_python生成器。
记一下生成器的关键点:
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量有限。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
将列表元素按照某种算法推算出来,这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
生成器的概念,如下图所示,生成器g就是用来生成x的平方的东西,结果存在显示的内存地址里。
但是由于你还没说你到底要谁的平方,所以只能看到个地址不能看到答案。
L则不同,它是把所有答案穷举列在内存里了,你需要哪个就从里面找出来即可,比较耗费资源。而g则还没生成,需要哪个我现制造一个出来放在一个内存空间显示,节省了资源。
>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))
>>> g
at 0x1022ef630>
创建列表和生成器的区别仅在于最外层的[]
和()
,L
是一个list,而g
是一个generator。
如果一个函数定义中包含yield
关键字,那么这个函数就不再是一个普通函数,而是一个generator。
(理解生成器的执行很关键,多多思考,动手试一下)
如果需要生成器返回(下一个)值,需要调用.next()函数。其实当系统判断def是生成器时,就会自动支持.next()函数。
上一个例子看一下(例子转自博主,请见:yield理解)
def fib(max):
a, b = 1, 1
while a < max:
yield a
a, b = b, a+b
for n in fib(15):
print n
m = fib(13)
print m
print m.next()
print m.next()
print m.next()
fib()函数因为含有yield,被系统默认为是一个生成器。
for语句调用了fib(15)。当max=15时,进入fib()生成器,执行到yield a, 返回a值以及整个生成器暂停的状态,将a值赋给n, 打印出来;因为是for语句循环,所以又回到fib(15)语句,由于是生成器,因此从上次截断的位置开始执行,b值赋给a, a+b值赋给b,又因为是while语句,则继续while循环,yield a值,循环暂停跳出返回a值及生成器状态,把a值赋给n, 打印n。如此往复,一直循环到15结束。
m被赋了fib(13)这个生成器,每一次执行m.next()函数就会打印下一个值。
运行结果如下:
有了这些基础就可以考虑实现杨辉三角了,杨辉三角有几个特点:
1、每个数都等于它上方两数之和;
2、每行数字开头结尾都是1,左右对称;
3、数形的实质就是二项式定理,第n行的m个数可表示为 C(n-1,m-1),即为从n-1个不同元素中取m-1个元素的组合数;第n行的数字有n项;第n行数字和为2n-1。(忘记二项式可以移步百科--->二项式定理)。
思路:
我们把每一层看作一个list, 通过一个for循环,通过迭代,每次生成一个list,而生成器就在每一行生成list中起作用。
我们先定义一个函数yanghui_trigangle,作用是生成每一行的list,再通过for循环调用即可得到结果。
方法一:
以上为range函数容易混淆的地方。
#!/user/bin/env.python
# _*_ coding:utf-8 _*_
# _author:poiuyds
# 方法1
def yanghui_triangle():
L = [1]
while True:
yield L
# list(range(a,a))的输出为空
L = [1] + [L[i-1] + L[i] for i in range(1,len(L))] + [1]
#if __name__ == ' __main__':
n = 0
for i in yanghui_triangle():
print(i)
n += 1
if n > 10:
break
输出如下:
[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]
方法二:
# 方法2
def yh_triangle():
L = [1]
while True:
yield L
L.append(0)
# i所生成的每一项就是列表的一项
L = [L[i-1] + L[i] for i in range(len(L))]
n = 0
for i in yh_triangle():
print(i)
n += 1
if n > 10:
break
输出如下:
[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]