目录
切片操作的基本表达式:object[start:end:step]
系列目录
[Python|Git remote|hosts|PyCharm常用快捷键|变量转换|命名|类型|运算符|分支|调整tab|循环|语言基础50课:学习记录(1)-项目简介及变量、条件及循环]
[Python|list|切片|列表的运算符、比较及遍历|生成式|元素位置和次数|元素排序和反转|sort() 方法|嵌套的列表|语言基础50课:学习记录(2)-常用数据结构之列表]
[Python|元组|字符串|语言基础50课:学习记录(3)-常用数据结构之元组及字符串相关]
[Python|集合|运算|哈希码|语言基础50课:学习记录(4)-常用数据结构之集合]
[Python|字典|函数和模块|应用及进阶|分数符号(Latex)|String库|operator库|处理数据三步骤|语言基础50课:学习记录(5)-常用数据结构之字典、函数和模块应用及进阶]
[Python|装饰器|执行时间|递归|动态属性|静态方法和类|继承和多态|isinstance类型判断|溢出|“魔法”方法|语言基础50课:学习记录(6)-函数的高级应用、面向对象编程、进阶及应用]
[Python|xlwt|xlrd|调整单元格样式(背景,字体,对齐、虚线边框、列宽行高、添加公式)|xlutils|openpyxl|只读与只写|图表|语言基础50课:学习(8)]
[Python|python-docx|python-pptx|Pillow|smtplib|螺丝帽短信网关|正则表达式的应用|语言基础50课:学习(9)]
[Python|http|Chrome Developer Tools|Postman|HTTPie|builtwith库|python-whois库|爬虫及解析|语言基础50课:学习(10)]
[Python|线程和进程|阻塞|非阻塞|同步|异步|生成器和协程|资源竞争|进程间通信|aiohttp库|daemon属性值详解|语言基础50课:学习(11)]
[Python|并发编程|爬虫|单线程|多线程|异步I/O|360图片|Selenium及JavaScript|Scrapy框架|BOM 和 DOM 操作简介|语言基础50课:学习(12)]
[Python|MySQL概述|Windows-Linux-macOS安装|MySQL 基本命令|获取帮助|SQL注释|语言基础50课:学习(13)]
[Python|SQL详解之DDL|DML|DQL|DCL|索引|视图、函数和过程|JSON类型|窗口函数|接入MySQL|清屏|正则表达式|executemany|语言基础50课:学习(14)]
原项目地址:
https://hub.fastgit.org/jackfrued/Python-Core-50-Courses.git
8、常用数据结构之列表
有没有办法用一个变量来保存多个数据,有没有办法用统一的代码对多个数据进行操作?答案是肯定的,在Python中我们可以通过容器类型的变量来保存和操作多个数据,我们首先为大家介绍列表(list)这种新的数据类型。
定义和使用列表
```Python
items1 = list(range(1, 10))
print(items1) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
items2 = list('hello')
print(items2) # ['h', 'e', 'l', 'l', 'o']
```
列表的运算符
和字符串类型一样,列表也支持拼接、重复、成员运算、索引和切片以及比较运算,对此我们不再进行赘述,请大家参考下面的代码。
```Python
items1 = [35, 12, 99, 68, 55, 87]
items2 = [45, 8, 29]
# 列表的拼接
items3 = items1 + items2
print(items3) # [35, 12, 99, 68, 55, 87, 45, 8, 29]
# 列表的重复
items4 = ['hello'] * 3
print(items4) # ['hello', 'hello', 'hello']
# 列表的成员运算
print(100 in items3) # False
print('hello' in items4) # True
# 获取列表的长度(元素个数)
size = len(items3)
print(size) # 9
# 列表的索引
print(items3[0], items3[-size]) # 35 35
items3[-1] = 100
print(items3[size - 1], items3[-1]) # 100 100
# 列表的切片
print(items3[:5]) # [35, 12, 99, 68, 55] 从头开始到第5个数据(含第5个)
print(items3[4:]) # [55, 87, 45, 8, 100] 从第4个数以后(不含第4个)
print(items3[-5:-7:-1]) # [55, 68]
print(items3[::-2]) # [100, 45, 55, 99, 35] 从最后(-1)开始,每隔2个数据引用
补充:切片及索引介绍:
参考原文链接:https://blog.csdn.net/Zombie_QP/article/details/125063501
索引的一般方式
一个完整的切片是包含三个参数和两个冒号" : " ,用于分隔三个参数(start_index、end_index、step)。当只有一个“:”时,默认第三个参数step=1;当一个“:”也没有时,start_index=end_index,表示切取start_index指定的那个元素。
切片操作的基本表达式:object[start:end:step]
start:切片的起始位置,如果没有值的话从头开始. end:切片的结束位置,但不包含end(前闭后开),如果没有值的话表示切割到结束为止. step:步长,默认取值为1,如果步长为正数的情况表示从左往右,反正若为负数则表示从右往左. step的正负决定切的方向,这一点需要尤为注意!!!
切片操作的 详细切法
1.切割单个值
>> a = [1,2,3,4,5,6]
>>> a[0] ##单个数,代表位数,第0位就是a里面的第一位
1
>>> a[5]##a里面的第5位,注意要从0作为第一位开始数
6
2.切割完整对象
>>> b=[6,3,6,7,8,2,5,4]
>>> b[:] ##单独一个冒号,代表从头取到尾,步长默认为1
[6, 3, 6, 7, 8, 2, 5, 4]
>>> b[::]##单独两个冒号一样代表从头取到尾,步长默认为1
[6, 3, 6, 7, 8, 2, 5, 4]
>>> b[::-1]##注意,两个冒号后面是步长,步长为1,故应从右往左取
[4, 5, 2, 8, 7, 6, 3, 6]
即:
>>> b[::]==b[::1]==b[:]
Out[20]: True
3.当start和end全部为正数时.
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a[1:6] ##默认步长为1,从左往右,注意前闭后开
[1, 2, 3, 4, 5]
>>> a[1:6:-1]
[] ## 当取值的大小方向与步长的方向冲突时,返回值是空.
>>> a[6:1:-1] #不包含结尾,即按提取顺序方向,前闭后开
[6, 5, 4, 3, 2]
>>> a[:6] ## 没有star代表从头开始取,前闭后开
[0, 1, 2, 3, 4, 5]
>>> a[:6:-1] #结尾至6,反向提取,不包含结尾的6,前闭后开
[9, 8, 7]
>>> a[6:] #从6至尾
[6, 7, 8, 9]
>>> a[6::-1] #从6开始包含6,反向截取至开头
[6, 5, 4, 3, 2, 1, 0]
4.当start和end全部取负数的时.
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a[:-6] ## -6意思是从右往左数的第六位,故第六位是4,然后默认步长为1(从右往左),star未写,故从头开始取到4,前闭后开不取4
[0, 1, 2, 3]
>>> a[-1:-6] #没有第三位,默认为1,正向选取,故为空
[]
>>> a[-1:-6:-1] #前闭后开
[9, 8, 7, 6, 5]
>>> a[-6:-1] ## 这个是从-6取到-1,步长为1,意思是从右往左数第6位到从右往左的第一位,前闭后开
[4, 5, 6, 7, 8]
>>> a[:-6:-1] ## 这个是从0取到-6,步长为-1,开头是冒号,终点为正,则从0开始,终点为为负,则从尾部开始,本例中为-1至-6,前闭后开(不包含-6)
[9, 8, 7, 6, 5]
>>> a[-6:] 这里的开头是4,前闭后开,如果结尾省略,则取至结尾,故全部输出
[4, 5, 6, 7, 8, 9]
>>> a[-6::-1] ## 注意这个不等于[-6:-1],区别是这里是::(两个冒号),两个冒号后连接的是步长,无结尾,则从起始位置,按从右向左全部输出
[4, 3, 2, 1, 0]
5.start和end是正负混合情况时
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a[1:-6] #前闭后开(不包含-6),步长缺省则为1
[1, 2, 3]
>>> a[1:-6:-1] #步长与首尾方向不一致,输出空白
[]
>>> a[-1:6] #这里默认步长为+1,故不一致,输出空白
[]
>>> a[-1:6:-1] #前闭后开(不包含-6),步长为-1,由右向左输出
[9, 8, 7]
6.连续的切片操作
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a[:8][2:5][-1:] ## [:8]就是0取到8,在从其中取2到5,最后取-1位
[4]
a[:8] ---- [0,1,2,3,4,5,6,7]
[0,1,2,3,4,5,6,7][2:5]----[2,3,4]
[2,3,4][-1:] ----[4]
7.切片中的三个参数为表达式
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a[1+2:2*3:7%2] ## 思路一样,运算出来,继续切
[3, 4, 5]
-
4
8.切片可以操作其他的对象
>>> t = (1,2,3,4,5)
>>> t[1:3]
(2, 3)
>>> s = "ACDRF" ##切片在字母上也是可以使用的,所以说切片很强大
>>> s[1:3]
'CD'
>>> (0, 1, 2, 3, 4, 5)[:3]#元组的切片操作
>>> (0, 1, 2)
>>> for i in range(0,100):
... print(i)
...
>>> for i in range(0,100)[2::3][-10:]: ## 意思是从第二位开始取,步长为3,[-10]则是从倒数10位开始取,意思是去末尾10位.
... print(i)
...
71
74
77
80
83
86
89
92
95
98
列表的比较运算
items5 = [1, 2, 3, 4]
items6 = list(range(1, 5)) #range含头不含尾
# 两个列表比较相等性比的是对应索引位置上的元素是否相等
print(items5 == items6) # True
items7 = [3, 2, 1]
# 两个列表比较大小比的是对应索引位置上的元素的大小
print(items5 <= items7) # True
item[-3] [-2] [-1]
等价于:
item[0 ] [ 1 ] [ 2 ]
item [ len(item) -1]
值得一提的是,由于列表是可变类型,所以通过索引操作既可以获取列表中的元素,也可以更新列表中的元素。对列表做索引操作一样要注意索引越界的问题,对于有`N`个元素的列表,正向索引的范围是`0`到`N-1`,负向索引的范围是`-1`到`-N`,如果超出这个范围,将引发`IndexError`异常,错误信息为:`list index out of range`。
列表元素的遍历
如果想逐个取出列表中的元素,可以使用`for`循环的,有以下两种做法。
方法一:
```Python
items = ['Python', 'Java', 'Go', 'Kotlin']
for index in range(len(items)):
print(items[index])
```
方法二:list本身就具有循环索引的属性
```Python
items = ['Python', 'Java', 'Go', 'Kotlin']
for item in items:
print(item)
```
讲到这里,我们可以用列表的知识来重构上面“掷色子统计每个点数出现次数”的代码。
```Python
import random
counters = [0] * 6
for _ in range(6000):
face = random.randint(1, 6)
counters[face - 1] += 1
for face in range(1, 7):
print(f'{face}点出现了{counters[face - 1]}次')
```
上面的代码中,我们用`counters`列表中的六个元素分别表示1到6的点数出现的次数,最开始的时候六个元素的值都是`0`。接下来用随机数模拟掷色子,如果摇出1点`counters[0]`的值加`1`,如果摇出2点`counters[1]`的值加`1`,以此类推。大家感受一下,这段代码是不是比之前的代码要简单优雅很多。
列表的方法
和字符串一样,列表类型的方法也很多,下面为大家讲解比较重要的方法。
添加和删除元素
```Python
items = ['Python', 'Java', 'Go', 'Kotlin']
# 使用append方法在列表尾部添加元素
items.append('Swift')
print(items) # ['Python', 'Java', 'Go', 'Kotlin', 'Swift']
# 使用insert方法在列表指定索引位置插入元素
items.insert(2, 'SQL') #2为待出入元素在原list中的索引位置
print(items) # ['Python', 'Java', 'SQL', 'Go', 'Kotlin', 'Swift']
# 删除指定的元素
items.remove('Java')
print(items) # ['Python', 'SQL', 'Go', 'Kotlin', 'Swift']
# 删除指定索引位置的元素
items.pop(0)
items.pop(len(items) - 1)
print(items) # ['SQL', 'Go', 'Kotlin']
# 清空列表中的元素
items.clear()
print(items) # []
```
需要提醒大家,在使用`remove`方法删除元素时,如果要删除的元素并不在列表中,会引发`ValueError`异常,错误消息是:`list.remove(x): x not in list`。在使用`pop`方法删除元素时,如果索引的值超出了范围,会引发`IndexError`异常,错误消息是:`pop index out of range`。
从列表中删除元素其实还有一种方式,就是使用Python中的`del`关键字后面跟要删除的元素,这种做法跟使用`pop`方法指定索引删除元素没有实质性的区别,但后者会返回删除的元素,前者在性能上略优(`del`对应字节码指令是`DELETE_SUBSCR`,而`pop`对应的字节码指令是`CALL_METHOD`和`POP_TOP`,不理解就跳过,不用管它!!!)。
```Python
items = ['Python', 'Java', 'Go', 'Kotlin']
del items[1]
print(items) # ['Python', 'Go', 'Kotlin']
```
元素位置和次数
列表类型的`index`方法可以查找某个元素在列表中的索引位置;因为列表中允许有重复的元素,所以列表类型提供了`count`方法来统计一个元素在列表中出现的次数。请看下面的代码。
```Python
items = ['Python', 'Java', 'Java', 'Go', 'Kotlin', 'Python']
# 查找元素的索引位置
print(items.index('Python')) # 0
print(items.index('Python', 2)) # 5
# 注意:虽然列表中有'Java',但是从索引为3这个位置开始后面是没有'Java'的
print(items.index('Java', 3)) # ValueError: 'Java' is not in list
```
```Python
items = ['Python', 'Java', 'Java', 'Go', 'Kotlin', 'Python']
# 查找元素出现的次数
print(items.count('Python')) # 2
print(items.count('Go')) # 1
print(items.count('Swfit')) # 0
```
元素排序和反转
列表的`sort`操作可以实现列表元素的排序,而`reverse`操作可以实现元素的反转,代码如下所示。
```Python
items = ['Python', 'Java', 'Go', 'Kotlin', 'Python']
# 排序
items.sort()
print(items) # ['Go', 'Java', 'Kotlin', 'Python', 'Python']
# 反转
items.reverse()
print(items) # ['Python', 'Python', 'Kotlin', 'Java', 'Go']
```
sort() 方法详解
原文链接:https://blog.csdn.net/horses/article/details/122324556
sort() 方法执行的是原地(in place)排序,意味着它会改变列表中元素的位置。
默认情况下,sort() 方法使用小于运算符对列表元素进行排序。也就是说,更小的元素排在前面,更大的元素排在后面。
如果想要对列表元素进行从大到小排序,可以指定参数 reverse=True。
1、如果列表的元素为字符串,sort() 方法按照字母顺序进行排序。
2、如果列表的元素为数字,sort() 方法按照从小到大的顺序进行排序。
3、元组列表排序
假如存在以下由元组构成的列表:
companies = [('Google', 2019, 134.81),
('Apple', 2019, 260.2),
('Facebook', 2019, 70.7)]
现在我们想要按照收入从高到低对这些公司进行排序。
首先,指定一个排序关键字并传递给 sort() 方法。为了定义排序关键字,我们可以创建一个函数,参数为元组,返回值为排序的元素:
def sort_key(company):
return company[2]
以上 sort_key() 函数接收一个名为 company 的参数并返回它的第三个元素。其中,company 是一个元组(例如 (‘Google’, 2019, 134.81)),company[2] 代表了收入(例如 134.81)。
然后,将 sort_key 函数传递给 sort() 方法:
companies.sort(key=sort_key, reverse=True)
-
1
sort() 方法会使用函数 sort_key() 返回的结果进行比较。
注意,我们只需要将函数名 sort_key 传递给 sort() 方法,函数名后面没有括号。
完整的代码如下:
companies = [('Google', 2019, 134.81),
('Apple', 2019, 260.2),
('Facebook', 2019, 70.7)]
# define a sort key
def sort_key(company):
return company[2]
# sort the companies by revenue
companies.sort(key=sort_key, reverse=True)
# show the sorted companies
print(companies)
输出结果如下:
[('Apple', 2019, 260.2), ('Google', 2019, 134.81), ('Facebook', 2019, 70.7)]
使用 lambda 表达式
为了使代码更加精简, Python 允许定义没有名字的函数:
lambda arguments: expression
没有名字的函数被称为匿名函数,以上语句被称为 lambda 表达式。
从技术上来说,lambda 表达式等价于以下函数:
def name(arguments):
return expression
以下示例使用 lambda 表达式按照收入从低到高进行排序:
companies = [('Google', 2019, 134.81),
('Apple', 2019, 260.2),
('Facebook', 2019, 70.7)]
# sort the companies by revenue
companies.sort(key=lambda company: company[2])
# show the sorted companies
print(companies)
输出结果如下:
[('Facebook', 2019, 70.7), ('Google', 2019, 134.81), ('Apple', 2019, 260.2)]
-
1
列表的生成式
在Python中,列表还可以通过一种特殊的字面量语法来创建,这种语法叫做生成式。我们给出两段代码,大家可以做一个对比,看看哪一种方式更加简单优雅。
通过`for`循环为空列表添加元素。
```Python
# 创建一个由1到9的数字构成的列表
items1 = []
for x in range(1, 10):
items1.append(x)
print(items1)
# 创建一个由'hello world'中除空格和元音字母外的字符构成的列表
items2 = []
for x in 'hello world':
if x not in ' aeiou':
items2.append(x)
print(items2)
#['h', 'l', 'l', 'w', 'r', 'l', 'd']
# 创建一个由个两个字符串中字符的笛卡尔积构成的列表
items3 = []
for x in 'ABC':
for y in '12':
items3.append(x + y)
print(items3)
```
#['A1', 'A2', 'B1', 'B2', 'C1', 'C2']
通过生成式创建列表。
```Python
# 创建一个由1到9的数字构成的列表
items1 = [x for x in range(1, 10)]
print(items1) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
# 创建一个由'hello world'中除空格和元音字母外的字符构成的列表
items2 = [x for x in 'hello world' if x not in ' aeiou']
print(items2) # ['h', 'l', 'l', 'w', 'r', 'l', 'd']
# 创建一个由个两个字符串中字符的笛卡尔积构成的列表
items3 = [x + y for x in 'ABC' for y in '12']
print(items3) # ['A1', 'A2', 'B1', 'B2', 'C1', 'C2']
```
下面这种方式不仅代码简单优雅,而且性能也优于上面使用`for`循环和`append`方法向空列表中追加元素的方式。可以简单跟大家交待下为什么生成式拥有更好的性能,那是因为Python解释器的字节码指令中有专门针对生成式的指令(`LIST_APPEND`指令);而`for`循环是通过方法调用(`LOAD_METHOD`和`CALL_METHOD`指令)的方式为列表添加元素,方法调用本身就是一个相对耗时的操作。对这一点不理解也没有关系,记住“**强烈建议用生成式语法来创建列表**”这个结论就可以了。
嵌套的列表
[Python Tutor](<http://www.pythontutor.com/visualize.html>)网站的可视化代码执行功能,看看创建列表时计算机内存中发生了怎样的变化
如果列表中的元素又是列表,那么我们可以称之为嵌套的列表。嵌套的列表可以用来表示表格或数学上的矩阵,例如:我们想保存5个学生3门课程的成绩,可以定义一个保存5个元素的列表保存5个学生的信息,而每个列表元素又是3个元素构成的列表,分别代表3门课程的成绩。
```Python
scores = [[0] * 3 for _ in range(5)]
scores[0][0] = 95
print(scores)
# [[95, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
```