习题 38: 列表的操作 ******************************* 你已经学过了列表。在你学习“while 循环”的时候,你对列表进行过“追加(append)”\ 操作,而且将列表的内容打印了出来。另外你应该还在加分习题里研究过 Python 文档,\ 看了列表支持的其他操作。这已经是一段时间以前了,所以如果你不记得了的话,就回\ 到本书的前面再复习一遍把。 找到了吗?还记得吗?很好。那时候你对一个列表执行了 ``append`` 函数。不过,你\ 也许还没有真正明白发生的事情,所以我们再来看看我们可以对列表进行什么样的操作。 当你看到像 ``mystuff.append('hello')`` 这样的代码时,你事实上已经在 Python 内部\ 激发了一个连锁反应。以下是它的工作原理: 1. Python 看到你用到了 ``mystuff`` ,于是就去找到这个变量。也许它需要倒着检查看\ 你有没有在哪里用 ``=`` 创建过这个变量,或者检查它是不是一个函数参数,或者看\ 它是不是一个全局变量。不管哪种方式,它得先找到 ``mystuff`` 这个变量才行。 2. 一旦它找到了 ``mystuff`` ,就轮到处理句点 ``.`` (period) 这个操作符,而且开始\ 查看 ``mystuff`` 内部的一些变量了。由于 ``mystuff`` 是一个列表,Python 知道\ ``mystuff`` 支持一些函数。 3. 接下来轮到了处理 ``append`` 。Python 会将 "append" 和 ``mystuff`` 支持的所有函数\ 的名称一一对比,如果确实其中有一个叫 append 的函数,那么 Python 就会去使用这个函数。 4. 接下来 Python 看到了括号 ``(`` (parenthesis) 并且意识到, “噢,原来这应该是一个\ 函数”,到了这里,它就正常会调用这个函数了,不过这里的函数还要多一个参数才行。 5. 这个额外的参数其实是…… ``mystuff``! 我知道,很奇怪是不是?不过这就是 Python 的\ 工作原理,所以还是记住这一点,就当它是正常的好了。真正发生的事情其实是 ``append(mystuff, 'hello')`` ,不过你看到的只是 ``mystuff.append('hello')`` 。 大部分时候你不需要知道这些细节,不过如果你看到一个像这样的 Python 错误信息的时候,\ 上面的细节就对你有用了: .. code-block:: pycon $ python Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41) [GCC 4.4.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> class Thing(object): ... def test(hi): ... print "hi" ... >>> a = Thing() >>> a.test("hello") Traceback (most recent call last): File "", line 1, in TypeError: test() takes exactly 1 argument (2 given) >>> 就是这个吗?嗯,这个是我在 Python 命令行下展示给你的一点魔法。你还没有见过\ ``class`` 不过后面很快就要碰到了。现在你看到 Python 说 ``test() takes exactly 1 argument (2 given)`` (test() 只可以接受1个参数,实际上\ 给了两个)。它意味着 python 把 ``a.test("hello")`` 改成了 ``test(a, "hello")`` ,而有人弄错了,没有为它添加 ``a`` 这个参数。 一下子要消化这么多可能有点难度,不过我们将做几个练习,让你头脑中有一个深刻的印象。\ 下面的练习将字符串和列表混在一起,看看你能不能在里边找出点乐子来: .. literalinclude:: ex/ex39.py :linenos: 你应该看到的结果 =================== .. literalinclude:: ex/ex39.txt :language: console 加分习题 ============ 1. 将每一个被调用的函数以上述的方式翻译成 Python 实际执行的动作。例如: ``' '.join(things)`` 其实是 ``join(' ', things)`` 。 2. 将这两种方式翻译为自然语言。例如, ``' '.join(things)`` 可以翻译成“用 ' ' 连接(join) things”,而 ``join(' ', things)`` 的意思是“为 ' ' 和 things 调用 join 函数”。这其实是同一件事情。 3. 上网阅读一些关于“面向对象编程(Object Oriented Programming)”的资料。晕了吧?嗯,我以前也是。\ 别担心。你将从这本书学到足够用的关于面向对象编程的基础知识,而以后你还可以慢慢学到更多。 4. 查一下 Python中的 "class" 是什么东西。不要阅读关于其他语言的 "class" 的用法,这会让你更糊涂。 5. ``dir(something)`` 和 ``something`` 的 class 有什么关系? 6. 如果你不知道我讲的是些什么东西,别担心。程序员为了显得自己聪明,于是就发明了 Object Oriented Programming,简称为 OOP,然后他们就开始滥用这个东西了。如果你觉得这东西太难,\ 你可以开始学一下 “函数编程(functional programming)”。 常见问题回答 ========================== 你不是说别用 ``while-loop`` 吗? 是的。你要记住,有时候如果你有很好的理由,那么规则也是可以打破的。死守着规则不放的人是白痴。 ``stuff[3:5]`` 实现了什么功能? 这是一个列表切片动作,它会从 ``stuff`` 列表的第 3 个元素开始取值,直到第 5 个元素。注意,\ 这里并不包含第 5 个元素,这跟 ``range(3,5)`` 的情况是一样的。 为什么 ``join(' ', stuff)`` 不灵? ``join`` 的文档写得有问题。其实它不是这么工作的,其实它是你要插入的字符串的一个方法函数,\ 函数的参数是你要连接的字符串构成的数组,所以应该写作 ``' '.join(stuff)`` 。