# 练习38.列表操作
你已经学过了列表。在你学习“while循环”的时候,你对列表进行过“追加(append)”操作,而且将列表的内容打印了出来。另外你应该还在附加题里研究过 Python 文档,看了列表支持的其他操作。这已经是一段时间以前了,所以如果你不记得了的话,就回到本书的前面再复习一遍把。
找到了吗?还记得吗?很好。那时候你对一个列表执行了`append`函数。不过,你也许还没有真正明白发生的事情,所以我们再来看看我们可以对列表进行什么样的操作。
当你看到像 mystuff.append('hello') 这样的代码时,你事实上已经在 Python 内部激发了一个连锁反应。以下是它的工作原理:
> 1. 1.Python 看到你用到了`mystuff`,于是就去找到这个变量。也许它需要倒着检查看你有没有在哪里用`=`创建过这个变量,或者检查它是不是一个函数参数,或者看它是不是一个全局变量。不管哪种方式,它得先找到 mystuff 这个变量才行。
> 1. 一旦它找到了`mystuff`,就轮到处理句点`.`(period)这个操作符,而且开始查看`mystuff`内部的一些变量了。由于`mystuff`是一个列表,Python 知道它支持一些函数。
> 1. 接下来轮到了处理`append`。Python会将“append”和`mystuff`支持的所有函数的名称一一对比,如果确实其中有一个叫`append`的函数,那么 Python 就会去使用这个函数。
> 1. 接下来 Python 看到了括号`(` (parenthesis) 并且意识到, “噢,原来这应该是一个函数”,到了这里,它就正常会调用这个函数了,不过这里的函数还要多一个参数才行。
> 1. 这个额外的参数其实是……`mystuff`!我知道,很奇怪是不是?不过这就是 Python 的工作原理,所以还是记住这一点,就当它是正常的好了。真正发生的事情其实是 `append(mystuff, 'hello')` ,不过你看到的只是 `mystuff.append('hello')` 。
大部分时候你不需要知道这些细节,不过如果你看到一个像这样的 Python 错误信息的时候,上面的细节就对你有用了:
~~~
$ 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 "<stdin>", line 1, in <module>
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`这个参数。
一下子要消化这么多可能有点难度,我们将做几个练习,让你头脑中有一个深刻的印象。下面的练习将字符串和列表混在一起,看看你能不能在里边找出点乐子来:
~~~
ten_things = "Apples Oranges Crows Telephone Light Sugar"
print "Wait there are not 10 things in that list. Let's fix that."
stuff = ten_things.split(' ')
more_stuff = ["Day", "Night", "Song", "Frisbee", "Corn", "Banana", "Girl", "Boy"]
while len(stuff) != 10:
next_one = more_stuff.pop()
print "Adding: ", next_one
stuff.append(next_one)
print "There are %d items now." % len(stuff)
print "There we go: ", stuff
print "Let's do some things with stuff."
print stuff[1]
print stuff[-1] # whoa! fancy
print stuff.pop()
print ' '.join(stuff) # what? cool!
print '#'.join(stuff[3:5]) # super stellar!
~~~
## 你看到的结果
~~~
$ python ex38.py
Wait there are not 10 things in that list. Let's fix that.
Adding: Boy
There are 7 items now.
Adding: Girl
There are 8 items now.
Adding: Banana
There are 9 items now.
Adding: Corn
There are 10 items now.
There we go: ['Apples', 'Oranges', 'Crows', 'Telephone', 'Light', 'Sugar', 'Boy', 'Girl', 'Banana', 'Corn']
Let's do some things with stuff.
Oranges
Corn
Corn
Apples Oranges Crows Telephone Light Sugar Boy Girl Banana
Telephone#Light
~~~
## 列表能实现什么
假设你打算创建一个基于钓鱼的电脑游戏。如果你不知道什么是钓鱼,花点时间在网上找到相关资料看一看。要做到这些,你需要里了解一些关于“扑克牌”的概念,并将它们变成你的Python程序。你必须用python写出知道如何玩一副虚拟扑克牌的代码,这样人们就能把你的游戏当成真实的游戏来玩,即使它不是真的。你需要的是一副“扑克牌”结构,而程序员就称之为“数据结构”。
什么是数据结构呢?如果你仔细想想,数据结构其实就是一种正式的构造(组织)一些数据(事实)的方法。真的就是这么简单,尽管一些数据结构十分错综复杂,它们也仅仅是在程序中存储数据的方式而已,这样你就能用不同的方式访问它们。
我将在下一节练习中更深入的讲解这些,但是列表是程序员常用的数据结构之一。它们只是数据的有序列表,你可以通过线性索引来存储或访问它们。什么?记住我说过的话,只是因为一个程序员说过“列表是一个列表”并不意味着它比真实世界中的列表复杂多少。 让我们以扑克牌为例:
> 1. 你有一堆有值的卡片。
> 1. 这些卡片式一堆,一列,或者可以从头到尾排列这些卡片。
> 1. 你可以随机的从顶部、中部或者底部取出卡片。
> 1. 如果你想找到某张特殊的卡片, 你必须一张一张的检索这些卡片。
让我们看看我说过什么:
“一个有序的列表”是的,扑克牌有第一张和最后一张"有一些你要存储的事物"是的,卡片就是我要存储的东西"可以随机访问"是的,在这副牌中我可以任意取出一张."是线性的"是的,如果我想找到特定的一张牌,我必须从头开始按顺序查找。"有索引的"差不多, 如果我让你找到一副扑克牌的第19张,你就必须按照顺序去数,直到你找到这一张。在python的列表中,计算机可以直接跳到你给出的索引处。这就是一个列表做的所有的事情,这么解释应该给了你一个在编程中找到列表概念的方法吧。编程中的每一个概念通常都有与真实世界相关联,至少在真实世界是有用的。如果你能找出虚拟的概念在真实世界中对应的概念,那你也可以通过这些找到数据结构到底是做什么的。
## 什么情况可以使用列表
当你有一些有东西能匹配列表数据结构的有用特性时,使用列表:
> 1. 如果你需要维护一组次序,记住,这是把次序编成列表,而不是给次序排序,列表不会帮你排序。
> 1. 如果你需要根据一个随机数访问列表内容,记住,这时候基数从0开始。
> 1. 如果你需要从头到尾操作列表内容,记住,这就是for循环。
## 附加题
> 1. 将每一个被调用的函数以上述的方式翻译成 Python 实际执行的动作。比如`more_stuff.pop()` 是 `pop(more_stuff)`.
> 1. 将这两种方式翻译为自然语言。
> 1. 上网阅读一些关于“面向对象编程(Object Oriented Programming)”的资料。晕了吧?嗯,我以前也是。别担心。你将从这本书学到足够用的关于面向对象编程的基础知识,而以后你还可以慢慢学到更多。
> 1. 查一下 Python中的 “class” 是什么东西。不要阅读关于其他语言的 “class” 的用法,这会让你更糊涂。
> 1. 如果你不知道我讲的是些什么东西,别担心。程序员为了显得自己聪明,于是就发明了 Opject Oriented Programming,简称为 OOP,然后他们就开始滥用这个东西了。如果你觉得这东西太难,你可以开始学一下 “函数编程(functional programming)”。
> 1. 找出10种可以放在列表中的例子,并用它们写一些脚本。
## 常见问题
### Q:你没有说说不要用while循环?
> 是的,请记住,当需要的时候,你可以打破规则,只有蠢人才会一直一味的遵从规则。
### Q:`join(' ', stuff)`为什么没有生效?
> 文档中关于join的内容,写的没有意义,`join`是使用一个字符串将列表内容链接起来的一个方法,你可以试试这么写`' '.join(stuff).`.
### Q: 为什么你用了一个while循环?
> 试着用for循环改写一下,看看哪个更简单
### Q: `stuff[3:5]`实现了什么功能?
> 这句代码从`stuff`中获取了一个子集,包含stuff的第3和第4个元素,没有包含第5个元素。它和`range(3,5)`的工作原理相近。
- 序言
- 前言
- 简介
- 0:安装和准备
- 1:第一个程序
- 2:注释和“#”井号
- 3:数字和数学计算
- 4:变量和命名
- 5:更多的变量和打印
- 6:字符串和文本
- 7:更多的打印(输出)
- 8:打印, 打印
- 9:打印, 打印, 打印
- 10:那是什么?
- 11:提问
- 12:提示别人
- 13:参数, 解包, 变量
- 14:提示和传递
- 15:读文件
- 16:读写文件
- 17:更多文件操作
- 18:命名, 变量, 代码, 函数
- 19:函数和变量
- 20:函数和文件
- 21:函数的返回值
- 22:到目前为止你学到了什么?
- 23:阅读代码
- 24:更多的练习
- 25:更多更多的练习
- 26:恭喜你,可以进行一次考试了
- 27:记住逻辑
- 28:布尔表达式
- 29:IF 语句
- 30:Else 和 If
- 31:做出决定
- 32:循环和列表
- 33:while循环
- 34:访问列表元素
- 35:分支和函数
- 36:设计和调试
- 37:复习符号
- 38:列表操作
- 39:字典,可爱的字典
- 40:模块, 类和对象
- 41:学会说面向对象
- 42:对象、类、以及从属关系
- 43:基本的面向对象的分析和设计
- 44:继承Vs.包含
- 45:你来制作一个游戏
- 46:项目骨架
- 47:自动化测试
- 48:更复杂的用户输入
- 49:写代码语句
- 50:你的第一个网站
- 51:从浏览器获取输入
- 52:开始你的web游戏
- 来自老程序员的建议
- 下一步
- 附录A:命令行教程
- 简介
- 安装和准备
- 路径, 文件夹, 名录 (pwd)
- 如果你迷路了
- 创建一个路径 (mkdir)
- 改变当前路径 (cd)
- 列出当前路径 (ls)
- 删除路径 (rmdir)
- 目录切换(pushd, popd)
- 生成一个空文件(Touch, New-Item)
- 复制文件 (cp)
- 移动文件 (mv)
- 查看文件 (less, MORE)
- 输出文件 (cat)
- 删除文件 (rm)
- 退出命令行 (exit)
- 下一步