解数独,学编程-Python 4

python

上一篇我们使用了列表的生成方法, 用一条语句就可以根据现有的数据生成一个新的列表,避免了显式的循环,让代码显得非常简洁。

本次我们会继续分析cross这个函数的使用, 并用它来生成含有所有单元的列表的列表。

接下来我们在看两个例子:

# first column list , then row list, then 4x4 unit #
UNITLIST = ([cross(ROWS, c) for c in COLS] + [cross(r, COLS) for r in ROWS] + [cross(rs, cs) for rs in ('ABC','DEF','GHI') for cs in ('123','456','789')])

这条语句形成了一个新的列表,由三部分列表组成。

[cross(ROWS, c) for c in COLS]

编程时当遇到在一个抽象基础上累加另外一个抽象的时候,看起来就比较复杂了。 但是当我们抓住抽象的本质,就能理解代码的真实意图。

上面代码就是针对每个COLS中来的c,都做一下与ROWS中元素的组合。假如c为1, 则cross(ROWS, ‘1’) 就会生成 [‘A1’, ‘B1’, ‘C1’, ‘D1’ … ‘I1’] 这正好是第一列

如果c为2,则生成第二列, 所以 [cross(ROWS, c) for c in COLS] 生成的就是所有列组成的一个列表。

如果反回来思考,如何生成一个包含所有列的列表呢?

首先我们要明白, cross()函数的第二个参数不能是一个列表,因为该函数的算法是先取第一个参数中的一个元素不变,逐个与第二个参数中的某个元素组合。 如果第二个参数是列表且有多个元素, 新生成的列表元素第二部分就是变化的,不会像上面分析的结果一样,第二部分是不变的。

所以就先从列中取一个元素,作为cross函数的第二个参数。

那么,如何生成包含所有行的列表呢? 就是 [[‘A1’, ‘A2′,’A3’, ‘A4’ ,… ‘A9’], [‘B1’, ‘B2’, ‘B3’, … ‘B9’], … [‘I1’, ‘I2’, ‘I3’ … ‘I9’] ]?

cross(‘A’, COLS) , cross(‘B’, COLS) … cross(‘I’, COLS)

再把变化的部分抽出来,就变成了

[cross(r, COLS) for r in ROWS ]

这正好是 UNITLIST 中第二个部分,所有行的列表组合

下面我们来看如何生成3×3的方格的单元。 左上角的是[‘A1′,’A2′,’A3’, ‘B1’, ‘B2’, ‘B3’, ‘C1’, ‘C2’, ‘C3’], 中间的是 [‘A4’, ‘A5’, ‘A6’, ‘B4′,’B5′,’B6′,’C4′,’C5′,’C6’] 右上角的是 [‘A7′,’A8′,’A9’, ‘B7′,’B8’,’B9’, ‘C7’, ‘C8’, ‘C9’]

我们能找到什么规律呢?

我们可以看到,cross()的第一个参数‘ABC’, 第二个参数是 (‘123’,’456′, ‘789’)

中间一行最左边3×3单元是: [‘D1′,’D2’, ‘D3’, ‘E1’, ‘E2’, ‘E3’, ‘F1’, ‘F2’, ‘F3] 中间一个单元是 [‘D4′,’D5’, ‘D6’, ‘E4’, ‘E5, ‘E6’, ‘F4’, ‘F5’, ‘F6’] , 最右边的单元是 [‘D7′,’D8’, ‘D9’, ‘E7′,’E8′,’E9′]。cross()的第一个参数是‘DEF’, 第二个参数是 (‘123’,’456’, ‘789’)

由此,我们可以大胆地假设, 最后一行3×3单元, cross()的第一个参数是‘GHI’, 第二个参数是 (‘123’,’456′, ‘789’)

这正好是: [cross(rs, cs) for rs in (‘ABC’,’DEF’,’GHI’) for cs in (‘123′,’456′,’789’)]

所以看到了吧, UNITLIST 就是所有的单元, 包括行, 列,以及3×3的方格。所有这些单元,都保存在了UNITLIST这个变量里面了。

如果你仔细观察的话, 生成的列表中,有几个列表元素, 第一个参数就有几个元素。

本篇的主题就是根据cross函数和要实现的目的,来构造列表的生成式了。

看起来很复杂,只要理解了cross函数的本质,就容易掌握了。 只所以要学列表的生成式, 因为Python语言里面用得比较多,这样做简介,显得更加像Python程序员写的程序。

作业

根据cross()函数的定义,要实现 [‘A1’, ‘A2’, ‘A3’, ‘A4’], 应该怎么写构造列表的生成式呢?

cross(‘A’, [‘1′,’2′,’3′,’4’])

Leave a Reply

您的电子邮箱地址不会被公开。 必填项已用*标注