关于“可变对象和不可变对象”及“生成器函数”和“列表生成式”的实例说明

杨辉三角定义如下:

          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,'__')

 

 

待完善!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

posted @ 2019-06-17 18:27  对影成一双  阅读(147)  评论(0编辑  收藏  举报