2.学习python的列表和元组
0x00 什么是列表和元组
在python中我们若需要存储一组特定的数据组,就可以使用列表和元组了。它的使用方法跟我们学习C语言里面的数组差不多,不同在于不用指定数据的类型且列表使用方括号[]表示,元组使用圆括号()表示。列表是由一系列按照特定顺序排列的元素组成且可以对列表中的元素进行修改,元组是一组固定的元素组,对于元组中的各元素禁止任何修改操作。
0x01 列表简介
在列表中可以创建包含大小写字母、数字等组成的元素,所有的元素使用单引号''来包围,列表中使用逗号,来区分各个元素(后面的教程都以python3.x的版本来做介绍,为了方便大家多多接触python3.x,因为以后python2.x会逐渐被淘汰)如下举例所示:
corvin@workspace:~$ python3.4 Python 3.4.3 (default, Nov 28 2017, 16:41:13) [GCC 4.8.4] on linux Type "help", "copyright", "credits" or "license" for more information. >>> numbers = ['one', 'two', 'three', 'four', 'five'] >>> print(numbers) ['one', 'two', 'three', 'four', 'five']
由于列表是个有序集合,即列表中的各个元素都是有索引值,通过索引值可以访问列表中的任意元素,当取出某一元素后还可以调用前面对字符串的各操作函数也是可以的,在这里需要注意的是列表的索引值是从0开始的,即0表示列表中的第一个元素索引值,那1就表示列表中第二个元素索引值,同时还有一种特殊语法为了方便大家取出最后一个元素,那就是直接使用-1的索引值就可以访问列表中最后一个元素,-2就可以访问倒数第二个元素,以此类推。同时可以将列表中的值当作普通变量一样使用,拼接成新的字符串来使用:
>>> numbers = ['one', 'two', 'three', 'four', 'five'] >>> print(numbers) ['one', 'two', 'three', 'four', 'five'] >>> print(numbers[0]) one >>> print(numbers[1].title()) Two >>> print(numbers[1].upper()) TWO >>> print(numbers[-1]) five >>> print(numbers[-2].upper()) FOUR >>> print(numbers[-3].upper()) THREE >>> msg = "I have " + numbers[-1] +" apples." >>> print(msg) I have five apples.
创建的列表可以根据需要来修改、添加和删除其中的元素,例如你现在有4个水果,分别是苹果apple、橘子orange、香蕉banana和梨pear,那你吃掉一个水果列表中就少一个相应水果,如果现在又买了新的水果西瓜watermelon,那列表就需要增加这个新水果,当前列表始终保存有你当下还有的水果列表。如果想要修改列表中的某一个元素,直接指定列表名和要修改元素的索引,使用新值为该元素重新赋值即可:
>>> fruits = ['apple', 'orange', 'banana', 'pear'] >>> print(fruits) ['apple', 'orange', 'banana', 'pear'] >>> fruits[0]='apples' >>> print(fruits) ['apples', 'orange', 'banana', 'pear']
在现有的列表中添加元素有如下两种方式:
(1)在列表的末尾添加元素,直接使用append()方法即可,例如我们在网上购物时,购买商品列表开始是个空白列表,随着添加商品,该列表会逐渐增加:
>>> fruits = ['apple', 'orange', 'banana', 'pear'] >>> print(fruits) ['apple', 'orange', 'banana', 'pear'] >>> fruits.append('watermelon') >>> print(fruits) ['apple', 'orange', 'banana', 'pear', 'watermelon'] >>> >>> days = [] >>> days.append('monday') >>> days.append('tuesday') >>> days.append('wednesday') >>> print(days) ['monday', 'tuesday', 'wednesday']
(2)在列表中插入元素,使用insert()方法可以在列表的任意位置添加新元素,但是需要指定需要插入新元素的索引值,插入新元素会导致以前列表中的索引值后面的所有元素都右移一个位置:
>>> num = ['one', 'two', 'three'] >>> num.insert(0, 'zero') >>> print(num) ['zero', 'one', 'two', 'three'] >>> num.insert(1, 'new') >>> print(num) ['zero', 'new', 'one', 'two', 'three'] >>>
在列表中删除元素,总共有以下三种方式:
(1)使用del语句删除元素,前提是需要知道该元素在列表中的位置,且删除后就无法再访问该元素了:
>>> fruits = ['apple', 'orange', 'banana', 'pear'] >>> print(fruits) ['apple', 'orange', 'banana', 'pear'] >>> del fruits[1] >>> print(fruits) ['apple', 'banana', 'pear'] >>> del fruits[0] >>> print(fruits) ['banana', 'pear'] >>>
(2)使用pop()删除元素,该方法操作列表就像操作一个栈,pop的元素每次都是最后的栈顶元素,当然如果想pop出任意位置的元素,只需要在pop()的括号中指定要删除的元素索引即可:
>>> fruits = ['apple', 'orange', 'banana', 'pear'] >>> pop_fruit = fruits.pop() >>> print(fruits) ['apple', 'orange', 'banana'] >>> print("Pop out fruit is " + pop_fruit.title() + " !") Pop out fruit is Pear ! >>> pop_fruit = fruits.pop(1) >>> print(fruits) ['apple', 'banana'] >>> print("Pop out fruit is " + pop_fruit.title() + " !") Pop out fruit is Orange ! >>>
(3)根据值来删除元素,有时不知道想要删除的元素在列表中的具体位置,那么只需知道该元素值也是可以删除的,那就是调用remove(),当然我们还可以使用一个变量将要删除的元素先保存起来,然后再删除该指定元素,这样后面还可以对已删除的变量进行操作。同时还需要注意remove()只会删除第一个指定的元素,如果要删除的元素在列表中出现多次的话,就需要使用个循环来依次判断是否删除了所有的指定元素:
>>> fruits = ['apple', 'orange', 'banana', 'pear', 'watermelon'] >>> print(fruits) ['apple', 'orange', 'banana', 'pear', 'watermelon'] >>> fruits.remove('pear') >>> print(fruits) ['apple', 'orange', 'banana', 'watermelon'] >>> fruits.remove('orange') >>> print(fruits) ['apple', 'banana', 'watermelon'] >>> remove_fruit = 'apple' >>> fruits.remove(remove_fruit) >>> print(fruits) ['banana', 'watermelon'] >>> print("Removed " + remove_fruit.upper() + " fruit just now!") Removed APPLE fruit just now! >>> >>> fruits.append('peach') >>> fruits.insert(0, 'peach') >>> print(fruits) ['peach', 'banana', 'watermelon', 'peach'] >>> fruits.remove('peach') >>> print(fruits) ['banana', 'watermelon', 'peach'] >>>
对列表进行排序,python使用sort()函数对列表中元素按照字母顺序进行排列,默认是按照字母从小到大顺序排列,如果想要按照从大大小顺序来排列需要加上reverse=True参数,使用sort()可以对列表中元素进行永久性排序,sorted()用法跟sort()是差不多的,唯一不同地方是排序只是临时排序,不改变原列表中元素的排列顺序。如果想把整个列表中元素永久的反序排列,直接使用reverse()方法即可,如果想还原成原始的排列顺序,只要再调用一次reverse()即可:
>>> alpha = ['a', 'c', 'b', 'e', 'd'] >>> print(alpha) ['a', 'c', 'b', 'e', 'd'] >>> alpha.sort() >>> print(alpha) ['a', 'b', 'c', 'd', 'e'] >>> alpha.sort(reverse=True) >>> print(alpha) ['e', 'd', 'c', 'b', 'a'] >>> >>> alpha = ['a', 'c', 'b', 'e', 'd'] >>> print(sorted(alpha)) ['a', 'b', 'c', 'd', 'e'] >>> print(alpha) ['a', 'c', 'b', 'e', 'd'] >>> print(sorted(alpha, reverse=True)) ['e', 'd', 'c', 'b', 'a'] >>> >>> alpha = ['a', 'c', 'b', 'e', 'd'] >>> alpha.sort() >>> print(alpha) ['a', 'b', 'c', 'd', 'e'] >>> alpha.reverse() >>> print(alpha) ['e', 'd', 'c', 'b', 'a'] >>> alpha.reverse() >>> print(alpha) ['a', 'b', 'c', 'd', 'e']
获取列表元素个数,避免在使用列表索引时出错,使用函数len()可以快速获取列表元素个数,如果在访问列表中元素时,索引超出范围会导致程序异常:
>>> fruits = ['apple', 'orange', 'banana', 'pear', 'watermelon'] >>> print(len(fruits)) 5 >>> print(fruits[4]) watermelon >>> print(fruits[5]) Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: list index out of range >>>
0x02 操作列表
学会了创建简单的列表后就可以来遍历整个列表了,因为我们将数据保存进列表就是为了后面的各种操作,那遍历整个列表就是必不可少的操作,接下来介绍使用for循环来遍历列表中元素,注意在for语句末尾有一个冒号:,用来提示python下一行是循环的第一行,同时还需要注意python是根据缩进来判断代码行与前一行的关系,一般缩进都是4个空格,在for循环下面一行必须要有一个缩进行,如果没有会报错,当需要在for循环中执行多个操作时,那么就需要将多行代码都缩进相同空格即可:
>>> fruits = ['apple', 'orange', 'banana', 'pear', 'watermelon'] >>> for fruit in fruits: ... print(fruit) ... apple orange banana pear watermelon >>> >>> for fruit in fruits: ... print("There is " + fruit.title() + " fruit.") ... There is Apple fruit. There is Orange fruit. There is Banana fruit. There is Pear fruit. There is Watermelon fruit. >>> >>> for fruit in fruits: ... print("There is " + fruit.title() + " fruit.") File "<stdin>", line 2 print("There is " + fruit.title() + " fruit.") ^ IndentationError: expected an indented block >>> for fruit in fruits: ... print("There is " + fruit.title() + " fruit.") ... print("I like this fruit.") ... There is Apple fruit. I like this fruit. There is Orange fruit. I like this fruit. There is Banana fruit. I like this fruit. There is Pear fruit. I like this fruit. There is Watermelon fruit. I like this fruit.
创建数值列表,在python中使用range()函数可以很方便的生成一系列的数字,同时还可指定步长,即每次增加几,在range中第一个参数是初始值,第二个参数是最大值,第三个参数是增加的步进值。同时还可以使用list()函数将range()的结果转换成数字列表。在python中使用两个星号**表示乘方运算:
>>> for num in range(1, 5): ... print(num) ... 1 2 3 4 >>> for num in range(1, 10, 2): ... print(num) ... 1 3 5 7 9 >>> numbers = list(range(1,5)) >>> print(numbers) [1, 2, 3, 4] >>> >>> squars = [] >>> for num in range(1, 5): ... squars.append(num**2) ... >>> print(squars) [1, 4, 9, 16]
对数字列表执行简单统计计算,可以使用min,max,sum函数来找出列表的最小值,最大值和对列表所有元素求和:
>>> numbers=list(range(1,5)) >>> print(numbers) [1, 2, 3, 4] >>> print(min(numbers)) 1 >>> print(max(numbers)) 4 >>> print(sum(numbers)) 10
列表解析,使用这种方式可以将for循环和创建新元素的代码合并成一行,并自动将新元素添加到列表中,大大减少代码行数。列表解析的形式例子: nums = [value**2 for value in range(1,5)],该语法流程是首先计算for循环得到其输出1,2,3,4,将其输出通过value**2计算得到结果1,4,9,16,然后将最终的输出添加在nums列表中,这样就通过一行代码完成了整个过程:
>>> nums = [value**2 for value in range(1,5)] >>> print(nums) [1, 4, 9, 16] >>> >>> nums = [] >>> for value in range(1,5): ... nums.append(value**2) ... >>> print(nums) [1, 4, 9, 16] >>>
列表的切片,就是访问列表的一部分有效数据,通过在列表名后面的方括号里添加两个起始和截止元素的索引,还有一些情况如果不指定第一个起始索引,那么默认从开头0元素开始,若不指定第二个索引,那么默认一直取到末尾最后一个元素。前面还介绍过为了方便大家从后面开始计算元素的索引,使用了-1最为最后一个元素的索引,-2倒数第二个索引,使用这个也能方便我们取到想要的列表片段,举例说明:
>>> fruits = ['apple', 'orange', 'banana', 'pear', 'watermelon'] >>> print(fruits[0:3]) ['apple', 'orange', 'banana'] >>> print(fruits[2:4]) ['banana', 'pear'] >>> >>> print(fruits[:4]) ['apple', 'orange', 'banana', 'pear'] >>> print(fruits[1:]) ['orange', 'banana', 'pear', 'watermelon'] >>> >>> print(fruits[-3:]) ['banana', 'pear', 'watermelon'] >>> print(fruits[:-1]) ['apple', 'orange', 'banana', 'pear'] >>> print(fruits[-4:-2]) ['orange', 'banana'] >>>
使用for循环来遍历列表的切片,我们经常需要把我们取出的列表元素进行特殊操作,此时就需要for循环了:
>>> fruits = ['apple', 'orange', 'banana', 'pear', 'watermelon'] >>> for fruit in fruits[1:4]: ... print("I like " + fruit.title() + " fruit.") ... I like Orange fruit. I like Banana fruit. I like Pear fruit.
复制整个列表,我们就可以来创建一个包含整个列表的切片,即在方括号中只写一个冒号,省略第一第二个索引,这样将其赋值给一个新的列表这样就完成了复制列表,需要注意的是这两个列表是不同的两个列表,对其中一个列表操作不会影响另外一个列表。如果我们想要两个列表完全一样的话就不能使用切片的形式来赋值了,就直接将原始列表名赋值给新列表,这样的话两个列表就完全相同,对其中新列表操作,相应的原始列表也会有相同的影响,例如新建一个new_list列表,我们使用count为其赋值,这样对new_list进行添加元素的话,那么count列表即使没有任何操作也会发现新增了跟new_list一样的元素:
>>> fruits = ['apple', 'orange', 'banana', 'pear', 'watermelon'] >>> count = fruits[:] >>> print(fruits) ['apple', 'orange', 'banana', 'pear', 'watermelon'] >>> print(count) ['apple', 'orange', 'banana', 'pear', 'watermelon'] >>> >>> count.append('grape') >>> fruits.append('mango') >>> print(count) ['apple', 'orange', 'banana', 'pear', 'watermelon', 'grape'] >>> print(fruits) ['apple', 'orange', 'banana', 'pear', 'watermelon', 'mango'] >>> >>> new_list = count >>> print(new_list) ['apple', 'orange', 'banana', 'pear', 'watermelon', 'grape'] >>> print(count) ['apple', 'orange', 'banana', 'pear', 'watermelon', 'grape'] >>> new_list.append('mango') >>> print(new_list) ['apple', 'orange', 'banana', 'pear', 'watermelon', 'grape', 'mango'] >>> print(count) ['apple', 'orange', 'banana', 'pear', 'watermelon', 'grape', 'mango']
0x03 元组
列表非常适合存储那些在运行过程中可能会变化的数据集,列表中元素可以修改,但是如果想存储一组不想被任意修改的数据集就需要用元组了,元组跟列表的表达方式不同就是用圆括号来标识,同样的也可以通过索引来访问元组中的元素。当尝试为元组中元素赋予新值时会提示错误“TypeError: 'tuple' object does not support item assignment”,同样也可以使用for循环来遍历元组中所有元素:
>>> tuple = (10,20,30,40,50) >>> print(tuple) (10, 20, 30, 40, 50) >>> print(tuple[2]) 30 >>> print(max(tuple)) 50 >>> print(min(tuple)) 10 >>> print(sum(tuple)) 150 >>> tuple[0]=11 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'tuple' object does not support item assignment >>> >>> for num in tuple: ... print("num = " + str(num)) ... num = 10 num = 20 num = 30 num = 40 num = 50
相比于列表,元组是更简单的数据结构,如果需要存储一组值在程序的整个运行周期内都不变,禁止被修改的话,就需要使用元组了。
0x04 注意事项
[1].以上所有的演示操作都是在python3.4的版本中进行的,为了让大家更快的熟悉python3.x的编程习惯.
0x05 参考资料
[1].Eric Matthes 著 袁国忠 译. Python编程从入门到实践[M]. 北京:中国工信出版社 人民邮电出版社. 2017. 31-63
0x06 问题反馈
大家在按照教程操作过程中有任何问题,可以关注ROS小课堂的官方微信公众号,在公众号中给我发消息反馈问题即可,我基本上每天都会处理公众号中的留言!当然如果你要是顺便给ROS小课堂打个赏,我也会感激不尽的,打赏30块还会邀请进ROS小课堂的微信群与更多志同道合的小伙伴一起学习和交流!