现在让我们以“列表”(list)为例来了解一下Python的复合数据类型,复合数据是其他数据类型的容器。如果你把逗号分隔的多个值用方括号括起来,就定义了一个列表,组成列表的单个数据项称为“元素”,同一个列表中的元素类型可以各不相同,列表也可以作为另一个列表中的元素:
In [1]: x = [1, 2, 3, "abc"]
In [2]: x
Out[2]: [1, 2, 3, 'abc']
In [3]: type(x)
Out[3]: list
In [4]: y = [] # 定义一个空列表
In [5]: type(y)
Out[5]: list
列表类型是一种“序列”(Sequence),即其中的元素有先后顺序——序列是程序语言中的一个抽象概念,实际上字符串也属于序列,只不过字符串中的元素只能是单个字符。任何序列都有“长度”即所包含元素的个数,序列中的每个元素都有“索引号”或叫“序号”——第一个元素序号为0,第二个为1;或者也可以倒着数——倒数第一个元素序号为-1,倒数第二个为-2,依次类推。在序列之后再加上方括号括起来的数字序号,可以做返回一个或多个元素的选取操作:
In [6]: len(x) # len函数返回序列的长度
Out[6]: 4
In [7]: x[1] # 返回1号元素
Out[7]: 2
In [8]: x[-1] # 返回-1号元素
Out[8]: 'abc'
In [9]: x[0:2] # 返回包含0号至2号元素的新列表,注意选取区间左开右闭
Out[9]: [1, 2]
In [10]: x[:2] # 从头开始选取则序号可以省略
Out[10]: [1, 2]
In [11]: "python"[-3:-1] # 倒数选取区间仍是左开右闭
Out[11]: 'ho'
In [12]: "python"[1:-1] # 正数倒数可以混用
Out[12]: 'ytho'
In [13]: "python"[::2] # 第三个数字指定“步长”间隔选取
Out[13]: 'pto'
In [14]: "python"[::-1] # 步长为负值表示反序选取
Out[14]: 'nohtyp'
序列还有一些共同的“方法”(Method)——所谓方法其实就是函数,但与直接定义在模块之下的普通函数不同,方法定义在类型中,是类型的“成员函数”。任何序列对象都可以引用index方法返回某个元素首次出现的序号,引用count方法返回某个元素的出现次数;具体的数据类型还有各自专属的方法,例如字符串的upper/lower方法可以转换大小写,split方法可以拆分单词;列表可以用append方法添加新元素,remove方法移除一个元素等等:
In [15]: y="Life is short, you need Python."
In [16]: y.index("n")
Out[16]: 19
In [17]: y.count("n")
Out[17]: 2
In [18]: y.upper()
Out[18]: 'LIFE IS SHORT, YOU NEED PYTHON.'
In [19]: y.split() # 以空格拆分原字符串为一个列表
Out[19]: ['Life', 'is', 'short,', 'you', 'need', 'Python.']
In [20]: x.append("python") # 列表添加一个新元素
In [21]: x
Out[21]: [1, 2, 3, 'abc', 'python']
In [22]: x.remove("abc") # 列表移除指定元素(如有重复只移除第一个)
In [23]: x
Out[23]: [1, 2, 3, 'python']
In [24]: x[2] = True
In [25]: x
Out[25]: [1, 2, True, 'python']
上面的练习体现了列表的一个重要性质:列表对象“可变”(Mutable),而我们之前接触过的数据类型都“不可变”(Immutable),例如字符串转换大小写实际上是返回了一个新字符串对象;而列表则可以做“原地修改”——添加、删除或更新其中的元素,列表本身还是同一个对象,你可以用id函数来验证这一点。Python中还有一种“元组”(Tuple)类型——元组的元素是用圆括号括起来的,与列表的区别就在于它是不可变对象。
序列都支持进行“迭代”(Iterate)——就是“轮番”处理元素,每次都用下一个元素“替代”上一个元素,也可以说是一种特别循环,Python提供“for...in...”语句来进行迭代循环——“对于”某个对象“之内”的每个元素执行一次特定操作。Python还提供一个能生成整数序列的range函数用作“迭代器”,配合for语句执行指定次数的循环(用while语句实现则需要定义一个变量作为“计数器”):
In [26]: for i in x:
...: print(i)
...:
1
2
True
python
In [27]: for i in "abc":
...: print(i)
...:
a
b
c
In [28]: for i in range(5):
...: print(i)
...:
0
1
2
3
4
In [29]: list(range(5)) # list函数可以将迭代器转换为列表
Out[29]: [0, 1, 2, 3, 4]
接下来是一个综合性的练习——你已经知道在turtle绘图时可以使用颜色名,这些名称定义在一个rgb.txt文件里,让我们从该文件中获取所有颜色名并添加到一个列表中:
rgb_path = r"C:\Program Files\Python36\Tools\pynche\X\rgb.txt" # 文件路径
colors = []
with open(rgb_path) as file: # 打开文件
for line in file: # 每次读取一行
if not (line.isspace() or line.startswith("!")): # 空行或!打头的行则不必处理
# 最后一个制表符之后的字符串 split("\t")[-1]
# 再去掉末尾的换行符 [:-1] 就是颜色名
# 把颜色名添加进列表即可
colors.append(line.split("\t")[-1][:-1])
你可以注意到用Python操作文件非常简单,而且文件也属于可迭代的对象——执行以上程序就能得到颜色名列表colors,不过其中多单词的颜色名都有两种写法,一百多种灰色还都有英美两种拼法,让我们用remove方法去掉这些重复项:
for i in colors[:]: # 推荐这样返回一个新列表作为迭代器,否则原列表改变会影响循环次数
if " " in i or "grey" in i.lower():
colors.remove(i)
然后就可以把列表写进另一个文件:
file=open("colorslist.py", "w") # 以写入模式打开文件
file.write(str(colors)) # 列表转为字符串并写入文件
file.close() # 如果打开文件未用with语句,则要记得关闭文件
打开colorlist.py文件就能看到保存的列表,在列表前面加上“COLORS=”就可以作为模块成员引入了(大写表示定义的是“常量”)——以下程序用turtle绘图显示出所有的颜色:
import turtle as tt
def showcolor(x, y, color="black"):
"""显示颜色块和颜色名
"""
t = tt.Turtle()
t.hideturtle()
t.speed(0)
t.color(color)
t.penup()
t.setpos(x, y)
t.begin_fill()
for _ in range(4):
t.forward(16)
t.left(90)
t.forward(18)
t.end_fill()
t.color("black")
t.write(color)
def showcolors():
"""显示所有颜色
"""
from colorslist import COLORS
tt.TurtleScreen._RUNNING = True
tt.setup(1200, 820)
tt.setworldcoordinates(0, -810, 1200, 10)
tt.hideturtle()
tt.speed(0)
tt.tracer(0) # 关闭动效以减少耗时
tt.penup()
row = 0
col = 0
for color in COLORS:
showcolor(col * 100, row * -18, color)
row += 1
if row > 45:
row = 0
col += 1
tt.done()
if __name__ == "__main__":
showcolors()

——编程原来是这样……
编程小提示:autopep8
如果你想将一个程序文件快速修改为规范格式,可以安装autopep8这个第三方包 https://pypi.python.org/pypi/autopep8
例如要规范colorslist.py文件的格式,就输入以下系统命令:
autopep8 --in-place --aggressive colorslist.py
网友评论
参看这篇文章 https://www.jianshu.com/p/611f4f150c75