关于“可变对象和不可变对象”及“生成器函数”和“列表生成式”的实例说明
杨辉三角定义如下:
1
/ \
1 1
/ \ / \
1 2 1
/ \ / \ / \
1 3 3 1
/ \ / \ / \ / \
1 4 6 4 1
/ \ / \ / \ / \ / \
1 5 10 10 5 1
把每一行看做一个list,试写一个generator,不断输出下一行的list:
# -*- coding: utf-8 -*-
def triangles():
# 期待输出:
# [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]
n = 0
results = []
for t in triangles():
print(t)
results.append(t)
n = n + 1
if n == 10:
break
if results == [
[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]
]:
print('测试通过!')
else:
print('测试失败!')
下面进入实际代码编写及细节说明过程:
生成器是为了解决因元素个数极多、又有迭代公式而产生的浪费存储空间的函数式表达方式:有两种方式,请参考廖雪峰官网教程“生成器”;
方法一:弱方法
def triangles():
yield [1]
# 当某程序P1调用本生成器函数时,每遇到yield标志,就将相应的结果传送回去,中断此函数下面的程序,当P1再次调用此程序时,继续从上次中断
# 的地方往下执行,直到遇到下一个yield站点,如此反复运行
yield [1, 1]
s = (1, 1)
# 为了让 s 和 g 能够平行运行,互不影响,必须将 s 和 g 定义成不同的类型,以免改变 g 从而改变了 s中的内容,当然这并不是唯一的方法;
# 也可以通过 s.copy(g),从而使s和g指向不同的地址,进而互不影响。
# 所以一定要注意,对于list的复制要想清楚用途,到底是共用地址还是简单复制→分道扬镳;
g = [1, 1]
while True:
g[0] = 1
for i in range(len(s) - 1):
g[i + 1] = (s[i] + s[i + 1])
g.append(1)
s = tuple(g)
yield list(s)
# 以下是测试部分
n = 0
results = []
for t in triangles():
print(t)
results.append(t)
print(results)
n = n + 1
if n == 10:
break
print(results)
if results == [
[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]
]:
print('测试通过!')
else:
print('测试失败!')
方法二:神操作,可以借鉴其精妙之处
def triangles():
s = [1]
while True:
yield s
s = [1] + [s[x]+s[x+1] for x in range(len(s)-1)] +[1]
# 并没有着急给s赋值,而是遍历自身的元素产生一个完整新的序列,而后才把新序列赋值给s
# [s[x]+s[x+1] for x in range(len(s)-1)]采用了“列表生成式”的方法
# 整个函数是结合生成器generator 和 “列表生成式”两个思想完成的
# 生成器generator也可以当做可迭代对象进行遍历
# 下面附带range(0)的解释
a = [1,2,3,4,5,6,]
for i in range(0): # 不会报错,这个循环也不会执行,因为根本没产生可迭代的序列
print('__',i,'__')
待完善!!!!!!!!!!!!!!!!!!!!!!!!!!!!!