习题 41: 来自 Percal 25 号行星的哥顿人(Gothons) *********************************************************** 你在上一节中发现 dict 的秘密功能了吗?你可以解释给自己吗?让我来给你\ 解释一下,顺便和你自己的理解对比看有什么不同。这里是我们要讨论的代码: .. code-block:: python cities['_find'] = find_city city_found = cities['_find'](cities, state) 你要记住一个函数也可以作为一个变量,\``def find_city`` 比如这一句创建\ 了一个你可以在任何地方都能使用的变量。在这段代码里,我们首先把函数 ``find_city`` 放到叫做 ``cities`` 的字典中,并将其标记为 ``'_find'``\。 这和我们将州和市关联起来的代码做的事情一样,只不过我们在这里放了一个\ 函数的名称。 好了,所以一旦我们知道 ``find_city`` 是在字典中 ``_find`` 的位置,这就\ 意味着我们可以去调用它。第二行代码可以分解成如下步骤: 1. Python 看到 ``city_found =`` 于是知道了需要创建一个变量。 2. 然后它读到 ``cities`` ,然后知道了它是一个字典 3. 然后看到了 ``['_find']`` ,于是 Python 就从索引找到了字典 ``cities`` 中对应的位置,并且获取了该位置的内容。 4. ``['_find']`` 这个位置的内容是我们的函数 ``find_city`` ,所以 Python 就知道了这里表示一个函数,于是当它碰到 ``(`` 就开始了函数调用。 5. ``cities, state`` 这两个参数将被传递到函数 ``find_city`` 中,然后这个\ 函数就被运行了。 6. ``find_city`` 接着从 ``cities`` 中寻找 ``states`` ,并且返回它找到的\ 内容,如果什么都没找到,就返回一个信息说它什么都没找到。 7. Python ``find_city`` 接受返回的信息,最后将该信息赋值给一开始的 ``city_found`` 这个变量。 我再教你一个小技巧。如果你倒着阅读的话,代码可能会变得更容易理解。让我们\ 来试一下,一样是那行: 1. ``state`` 和 ``city`` 是... 2. 作为参数传递给... 3. 一个函数,位置在... 4. ``'_find'`` 然后寻找,目的地为... 5. ``cities`` 这个位置... 6. 最后赋值给 ``city_found``. 还有一种方法读它,这回是“由里向外”。 1. 找到表达式的中心位置,此次为 ``['_find']``. 2. 逆时针追溯,首先看到的是一个叫 ``cities`` 的字典,这样就知道了 cities 中的 ``_find`` 元素。 3. 上一步得到一个函数。继续逆时针寻找,看到的是参数。 4. 参数传递给函数后,函数会返回一个值。然后再逆时针寻找。 5. 最后,我们到了 ``city_found =`` 的赋值位置,并且得到了最终结果。 数十年的编程下来,我在读代码的过程中已经用不到上面的三种方法了。我只要瞟一眼\ 就能知道它的意思。甚至给我一整页的代码,我也可以一眼瞄出里边的 bug 和错误。这样\ 的技能是花了超乎常人的时间和精力才锻炼得来的。在磨练的过程中,我学会了下面\ 三种读代码的方法,它们适用于几乎所有的编程语言: 1. 从前向后。 2. 从后向前。 3. 逆时针方向。 下次碰到难懂的语句时,你可以试试这三种方法。 现在我们来写这次的练习,写完后再过一遍,这节习题其实挺有趣的。 .. literalinclude:: ex/ex41.py :linenos: 代码不少,不过还是从头写完吧。确认它能运行,然后玩一下看看。 你应该看到的结果 =================== 我玩起来时这样的: .. literalinclude:: ex/ex41.txt :language: console 加分习题 ============ 1. 解释一下返回至下一个房间的工作原理。 2. 创建更多的房间,让游戏规模变大。 3. 除了让每个函数打印自己以外,再学习一下“文档字符串(doc strings)”式的注解。\ 看看你能不能将房间描述写成文档注解,然后修改运行它的代码,让它把文档\ 注解打印出来。 4. 一旦你用了文档注解作为房间描述,你还需要让这个函数打印出用户提示吗?\ 试着让运行函数的代码打出用户提示来,然后将用户输入传递到各个函数。\ 你的函数应该只是一些 if 语句组合,将结果打印出来,并且返回下一个房间。 5. 这其实是一个小版本的“有限状态机(finite state machine)”,找资料\ 阅读了解一下,虽然你可能看不懂,但还是找来看看吧。 6. 我的代码里有一个 bug,为什么门锁要猜测 11 次? 常见问题回答 ========================== 怎样设计自己的游戏故事? 你可以自己编故事,也可以从书籍或者电影里找些简单场景。