Python基础
Python官网
廖雪峰
Python 详细视频 提取码: 2esp
PanDownload
林轩田机器学习基石 提取码: 2333
机器学习基石整个基石课程分成四个部分:
When Can Machine Learn?
Why Can Machine Learn?
How Can Machine Learn?
How Can Machine Learn Better?
The Learning Problem
一、What is Machine Learning
什么是“学习”?学习就是人类通过观察、积累经验,掌握某项技能或能力。就好像我们从小学习识别字母、认识汉字,就是学习的过程。而机器学习(Machine Learning),顾名思义,就是让机器(计算机)也能向人类一样,通过观察大量的数据和训练,发现事物规律,获得某种分析问题、解决问题的能力。
机器学习可以被定义为:Improving some performance measure with experence computed from data. 也就是机器从数据中总结经验,从数据中找出某种规律或者模型,并用它来解决实际问题。
什么情况下会使用机器学习来解决问题呢?其实,目前机器学习的应用非常广泛,基本上任何场合都能够看到它的身影。其应用场合大致可归纳为三个条件:
- 事物本身存在某种潜在规律
- 某些问题难以使用普通编程解决
- 有大量的数据样本可供使用
二、Applications of Machine Learning
机器学习在我们的衣、食、住、行、教育、娱乐等各个方面都有着广泛的应用,我们的生活处处都离不开机器学习。比如,打开购物网站,网站就会给我们自动推荐我们可能会喜欢的商品;电影频道会根据用户的浏览记录和观影记录,向不同用户推荐他们可能喜欢的电影等等,到处都有机器学习的影子。
三、Components of Machine Learning
本系列的课程对机器学习问题有一些基本的术语需要注意一下:
- 输入x
- 输出y
- 目标函数f,即最接近实际样本分布的规律
- 训练样本data
- 假设hypothesis,一个机器学习模型对应了很多不同的hypothesis,通过演算法A,选择一个最佳的hypothesis对应的函数称为矩g,g能最好地表示事物的内在规律,也是我们最终想要得到的模型表达式。
对于理想的目标函数f,我们是不知道的,我们手上拿到的是一些训练样本D,假设是监督式学习,其中有输入x,也有输出y。机器学习的过程,就是根据先验知识选择模型,该模型对应的hypothesis set(用H表示),H中包含了许多不同的hypothesis,通过演算法A,在训练样本D上进行训练,选择出一个最好的hypothes,对应的函数表达式g就是我们最终要求的。一般情况下,g能最接近目标函数f,这样,机器学习的整个流程就完成了。
四、Machine Learning and Other Fields
与机器学习相关的领域有:
数据挖掘(Data Mining)
人工智能(Artificial Intelligence)
统计(Statistics)
其实,机器学习与这三个领域是相通的,基本类似,但也不完全一样。机器学习是这三个领域中的有力工具,而同时,这三个领域也是机器学习可以广泛应用的领域,总得来说,他们之间没有十分明确的界线。
Learning to Answer Yes/No
机器学习的整个过程:根据模型H,使用演算法A,在训练样本D上进行训练,得到最好的h,其对应的g就是我们最后需要的机器学习的模型函数,一般g接近于目标函数f。本节将继续深入探讨机器学习问题,介绍感知机Perceptron模型,并推导课程的第一个机器学习算法:Perceptron Learning Algorithm(PLA)
一、Perceptron Hypothesis Set
引入这样一个例子:某银行要根据用户的年龄、性别、年收入等情况来判断是否给该用户发信用卡。现在有训练样本D,即之前用户的信息和是否发了信用卡。这是一个典型的机器学习问题,我们要根据D,通过A,在H中选择最好的h,得到g,接近目标函数f,也就是根据先验知识建立是否给用户发信用卡的模型。银行用这个模型对以后用户进行判断:发信用卡(+1),不发信用卡(-1)。
在这个机器学习的整个流程中,有一个部分非常重要:就是模型选择,即Hypothesis Set。选择什么样的模型,很大程度上会影响机器学习的效果和表现。下面介绍一个简单常用的Hypothesis Set:感知机(Perceptron)。
还是刚才银行是否给用户发信用卡的例子,我们把用户的个人信息作为特征向量$x$,令总共有d个特征,每个特征赋予不同的权重w,表示该特征对输出(是否发信用卡)的影响有多大。那所有特征的加权和的值与一个设定的阈值threshold进行比较:大于这个阈值,输出为+1,即发信用卡;小于这个阈值,输出为-1,即不发信用卡。感知机模型,就是当特征加权和与阈值的差大于或等于0,则输出$h(x)=1$;当特征加权和与阈值的差小于0,则输出$h(x)=-1$,而我们的目的就是计算出所有权值$w$和阈值threshold。
为了计算方便,通常我们将阈值threshold当做$w_{0}$,引入一个$x_{0}=1$的量与$w_{0}$相乘,这样就把threshold也转变成了权值$w_{0}$,,简化了计算。h(x)的表达式做如下变换:
为了更清晰地说明感知机模型,我们假设Perceptrons在二维平面上,即$h(x)=sign(w_0+w_1 x_1+w_2 x_2)$。其中,$w_0+w_1 x_1+w_2 x_2=0$是平面上一条分类直线,直线一侧是正类(+1),直线另一侧是负类(-1)。权重w不同,对应于平面上不同的直线。
那么,我们所说的Perceptron,在这个模型上就是一条直线,称之为linear(binary) classifiers。注意一下,感知器线性分类不限定在二维空间中,在3D中,线性分类用平面表示,在更高维度中,线性分类用超平面表示,即只要是形如$w^Tx$的的线性模型就都属于linear(binary) classifiers。
同时,需要注意的是,这里所说的linear(binary) classifiers是用简单的感知器模型建立的,线性分类问题还可以使用logistic regression来解决,后面将会介绍。
二、Perceptron Learning Algorithm(PLA)
根据上一部分的介绍,我们已经知道了hypothesis set由许多条直线构成。接下来,我们的目的就是如何设计一个演算法A,来选择一个最好的直线,能将平面上所有的正类和负类完全分开,也就是找到最好的g,使$g≈f$。
如何找到这样一条最好的直线呢?我们可以使用逐点修正的思想,首先在平面上随意取一条直线,看看哪些点分类错误。然后开始对第一个错误点就行修正,即变换直线的位置,使这个错误点变成分类正确的点。接着,再对第二个、第三个等所有的错误分类点就行直线纠正,直到所有的点都完全分类正确了,就得到了最好的直线。这种“逐步修正”,就是PLA思想所在。
下面介绍一下PLA是怎么做的:
首先随机选择一条直线进行分类。然后找到第一个分类错误的点,如果这个点表示正类,被误分为负类,即$w_t^Tx_{n(t)}<0$,那表示w和x夹角大于90度,其中w是直线的法向量。所以,x被误分在直线的下侧(相对于法向量,法向量的方向即为正类所在的一侧),修正的方法就是使w和x夹角小于90度。通常做法是$w\leftarrow w+yx,y=1$,如图右上角所示,一次或多次更新后的$w+yx$与x夹角小于90度,能保证x位于直线的上侧,则对误分为负类的错误点完成了直线修正。
按照这种思想,遇到个错误点就进行修正,不断迭代。要注意一点:每次修正直线,可能使之前分类正确的点变成错误点,这是可能发生的。但是没关系,不断迭代,不断修正,最终会将所有点完全正确分类(PLA前提是线性可分的)。这种做法的思想是“知错能改”,有句话形容它:“A fault confessed is half redressed.”
实际操作中,可以一个点一个点地遍历,发现分类错误的点就进行修正,直到所有点全部分类正确。这种被称为Cyclic PLA。
对PLA,我们需要考虑以下两个问题:
- PLA迭代一定会停下来吗?如果线性不可分怎么办?
- PLA停下来的时候,是否能保证$f \approx g$?如果没有停下来,是否有$f \approx g$?
三、Guarantee of PLA
PLA什么时候会停下来呢?根据PLA的定义,当找到一条直线,能将所有平面上的点都分类正确,那么PLA就停止了。要达到这个终止条件,就必须保证D是线性可分(linear separable)。如果是非线性可分的,那么,PLA就不会停止。
对于线性可分的情况,如果有这样一条直线,能够将正类和负类完全分开,令这时候的目标权重为$w_f$,则对每个点,必然满足$y_n=sign(w_f^Tx_n)$
PLA会对每次错误的点进行修正,更新权重$w_{t+1}$的值,如果$w_{t+1}$与$w_f$越来越接近,数学运算上就是内积越大,那表示$w_{t+1}$是在接近目标权重$w_f$,证明PLA是有学习效果的。所以,我们来计算$w_{t+1}$与$w_f$的内积.
从推导可以看出,$w_{t+1}$与$w_f$的内积跟$w_t$与$w_f$的内积相比更大了。似乎说明了$w_{t+1}$更接近$w_f$,但是内积更大,可能是向量长度更大了,不一定是向量间角度更小。所以,下一步,我们还需要证明$w_{t+1}$与$w_t$向量长度的关系.
$w_t$只会在分类错误的情况下更新,最终得到的$||w_{t+1}^2||$相比$||w_{t}^2||$的增量值不超过$max||x_n^2||$.也就是说,$w_t$的增长被限制了,$w_{t+1}$与$w_t$向量长度不会差别太大!
四、Non-Separable Data
上一部分,我们证明了线性可分的情况下,PLA是可以停下来并正确分类的,但对于非线性可分的情况,$w_f$实际上并不存在,那么之前的推导并不成立,PLA不一定会停下来。所以,PLA虽然实现简单,但也有缺点.
对于非线性可分的情况,我们可以把它当成是数据集D中掺杂了一下noise,事实上,大多数情况下我们遇到的D,都或多或少地掺杂了noise。这时,机器学习流程是这样的:
在非线性情况下,我们可以把条件放松,即不苛求每个点都分类正确,而是容忍有错误点,取错误点的个数最少时的权重w:
Types of Learning
上节课我们主要介绍了解决线性分类问题的一个简单的方法:PLA。PLA能够在平面中选择一条直线将样本数据完全正确分类。而对于线性不可分的情况,可以使用Pocket Algorithm来处理。本节课将主要介绍一下机器学习有哪些种类,并进行归纳。
一、Learning with Different Output Space Y
上节课引入的银行根据用户个人情况判断是否给他发信用卡的例子,这是一个典型的二元分类(binary classification)问题。也就是说输出只有两个,一般y={-1, +1},-1代表不发信用卡(负类),+1代表发信用卡(正类)。
二元分类的问题很常见,包括信用卡发放、垃圾邮件判别、患者疾病诊断、答案正确性估计等等。二元分类是机器学习领域非常核心和基本的问题。二元分类有线性模型也有非线性模型,根据实际问题情况,选择不同的模型。
除了二元分类,也有多元分类(Multiclass Classification)问题。顾名思义,多元分类的输出多于两个,y={1, 2, … , K}, K>2. 一般多元分类的应用有数字识别、图片内容识别等等。
二元分类和多元分类都属于分类问题,它们的输出都是离散值。二对于另外一种情况,比如训练模型,预测房屋价格、股票收益多少等,这类问题的输出y=R,即范围在整个实数空间,是连续的。这类问题,我们把它叫做回归(Regression)。最简单的线性回归是一种典型的回归模型。
除了分类和回归问题,在自然语言处理等领域中,还会用到一种机器学习问题:结构化学习(Structured Learning)。结构化学习的输出空间包含了某种结构在里面,它的一些解法通常是从多分类问题延伸而来的,比较复杂。本系列课程不会详细介绍Structured Learning,有兴趣的读者可以自行对它进行更深入的研究。
简单总结一下,机器学习按照输出空间划分的话,包括二元分类、多元分类、回归、结构化学习等不同的类型。其中二元分类和回归是最基础、最核心的两个类型,也是我们课程主要介绍的部分。
二、Learning with Different Data Label $y_n$
如果我们拿到的训练样本D既有输入特征x,也有输出$y_n$,那么我们把这种类型的学习称为监督式学习(Supervised Learning)。监督式学习可以是二元分类、多元分类或者是回归,最重要的是知道输出标签$y_n$。与监督式学习相对立的另一种类型是非监督式学习(Unsupervised learning)。非监督式学习是没有输出标签$y_n$的,典型的非监督式学习包括:聚类(clustering)问题,比如对网页上新闻的自动分类;密度估计,比如交通路况分析;异常检测,比如用户网络流量监测。通常情况下,非监督式学习更复杂一些,而且非监督的问题很多都可以使用监督式学习的一些算法思想来实现。
介于监督式和非监督式学习之间的叫做半监督式学习(Semi-supervised Learning)。顾名思义,半监督式学习就是说一部分数据有输出标签yn,而另一部分数据没有输出标签yn。在实际应用中,半监督式学习有时候是必须的,比如医药公司对某些药物进行检测,考虑到成本和实验人群限制等问题,只有一部分数据有输出标签$y_n$。
监督式、非监督式、半监督式学习是机器学习领域三个主要类型。除此之外,还有一种非常重要的类型:增强学习(Reinforcement Learning)。增强学习中,我们给模型或系统一些输入,但是给不了我们希望的真实的输出y,根据模型的输出反馈,如果反馈结果良好,更接近真实输出,就给其正向激励,如果反馈结果不好,偏离真实输出,就给其反向激励。不断通过“反馈-修正”这种形式,一步一步让模型学习的更好,这就是增强学习的核心所在。增强学习可以类比成训练宠物的过程,比如我们要训练狗狗坐下,但是狗狗无法直接听懂我们的指令“sit down”。在训练过程中,我们给狗狗示意,如果它表现得好,我们就给他奖励,如果它做跟sit down完全无关的动作,我们就给它小小的惩罚。这样不断修正狗狗的动作,最终能让它按照我们的指令来行动。实际生活中,增强学习的例子也很多,比如根据用户点击、选择而不断改进的广告系统.
简单总结一下,机器学习按照数据输出标签$y_n$划分的话,包括监督式学习、非监督式学习、半监督式学习和增强学习等。其中,监督式学习应用最为广泛。
三、Learning with Different Protocol $f(x_n,y_n)$
按照不同的协议,机器学习可以分为三种类型:
- Batch Learning
- Online
- Active Learning
batchlearning是一种常见的类型。batchlearning获得的训练数据D是一批的,即一次性拿到整个D,对其进行学习建模,得到我们最终的机器学习模型。batch learning在实际应用中最为广泛。
online是一种在线学习模型,数据是实时更新的,根据数据一个个进来,同步更新我们的算法。比如在线邮件过滤系统,根据一封一封邮件的内容,根据当前算法判断是否为垃圾邮件,再根据用户反馈,及时更新当前算法。这是一个动态的过程。之前我们介绍的PLA和增强学习都可以使用online模型。
active learning是近些年来新出现的一种机器学习类型,即让机器具备主动问问题的能力,例如手写数字识别,机器自己生成一个数字或者对它不确定的手写字主动提问。active learning优势之一是在获取样本label比较困难的时候,可以节约时间和成本,只对一些重要的label提出需求。
简单总结一下,按照不同的协议,机器学习可以分为batch, online, active。这三种学习类型分别可以类比为:填鸭式,老师教学以及主动问问题。
四、Learning with Different Input Space X
上面几部分介绍的机器学习分类都是根据输出来分类的,比如根据输出空间进行分类,根据输出y的标记进行分类,根据取得数据和标记的方法进行分类。这部分,我们将谈谈输入X有哪些类型。
输入X的第一种类型就是concrete features。比如说硬币分类问题中硬币的尺寸、重量等;比如疾病诊断中的病人信息等具体特征。concrete features对机器学习来说最容易理解和使用。
第二种类型是raw features。比如说手写数字识别中每个数字所在图片的mxn维像素值;比如语音信号的频谱等。raw features一般比较抽象,经常需要人或者机器来转换为其对应的concrete features,这个转换的过程就是Feature Transform。
第三种类型是abstract features。比如某购物网站做购买预测时,提供给参赛者的是抽象加密过的资料编号或者ID,这些特征X完全是抽象的,没有实际的物理含义。所以对于机器学习来说是比较困难的,需要对特征进行更多的转换和提取。
简单总结一下,根据输入X类型不同,可以分为concetet,raw,abstract。将一些抽象的特征转换为具体的特征,是机器学习过程中非常重要的一个环节。在《机器学习技法》课程中有详细介绍。
if else
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
30
31
32
gender = input("请输入你的性别:") #获取性别
#判断性别
if gender=="男": #input输入的全是str
print("高富帅")
elif gender=="女":
print("白富美")
else:
print("你很666")
#==================================================================================================================
score_s = input("请输入你的成绩")
score =int(score_s)
if score>=90 and score<=100:
print("本次考试等级为A")
elif score>=80 and score<90:
print("本次考试等级为B")
elif score>=70 and score<80:
print("本次考试等级为C")
elif score>=60 and score<70:
print("本次考试等级为D")
elif score>=0 and score<60:
print("本次考试等级为E")
#==================================================================================================================
import random
player = input("请输入:剪刀(0) 石头(1) 布(2):")
player = int(player)
computer = random.randint(0,2)
if((player == 0) and (computer == 2)) or ((player == 1) and (computer == 0)) or ((player ==2) and (computer == 1)):
print("获胜,哈哈,你太厉害了!")
elif player == computer:
print("平局,要不要再来一局")
else:
print("输了,不要走,洗洗手在接着来,决战到天明")
while
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
30
31
32
33
34
35
36
37
38
39
i = 0
while i<5:
print("当前是第%d次循环"%(i+1))
print("i=%d"%i)
i+=1
#================================================================
i =0
sum = 0
while i<=100:
sum = sum + i
i +=1
print("1到100的和是:%d"%sum)
#================================================================
i = 0
sum = 0
while i<= 100:
if i%2 == 0: #判断是否是偶数
sum = sum +i
i+=1
print("1到100的偶数和是%d"%sum)
#================================================================
i = 1
while i<=5:
j = 1
while j<=i:
print("* ",end='')
j+=1
print("\n")
i+=1
#================================================================
i = 1
while i<=9:
j=1
while j<=i:
print("%d*%d=%d "%(j,i,i*j),end='')
j+=1
print("\n")
i+=1
for
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
30
31
32
33
name = 'dongGe'
for x in name:
print(x)
else:
print("没有数据")
#================================================================
for x in name:
print("-----")
if x == 'g':
break
print(x)
#================================================================
for x in name:
print("-----")
if x == 'g':
continue
print(x)
#================================================================
i = 0
while i<10:
i+=1
print("-----")
if i == 5:
break #break的作用 : 用来结束整个循环
print(i)
#================================================================
i = 0
while i<10:
i+=1
print("-----")
if i==5:
continue #continue的作用 用来结束本次循环,紧接着执行下一次的循环
print(i)
List
列表是包含若干元素的有序连续内存空间
Python常用的序列结构:列表、元组、字典、字符串、集合等
Python内置对象:
对象类型 | 类型名称 | 示例 |
---|---|---|
数字 | int /float /complex | 1234/3.14/1.3e5/3+4j |
字符串 | str | ‘hello’ |
字节串 | bytes | b’hello world’ |
列表 | list | [1,2,3] |
字典 | dict | {1:’food’,2:’taste’} |
元组 | tuple | (2,-5,6) |
集合 | set/frozenset | {‘a’,’b’,’c’} |
布尔型 | bool | True /False |
空类型 | NoneType | None |
异常 | Exception | |
文件 | ||
其他迭代对象 | ||
编程单元 |
1 创建一个列表
1
2
3
4
5
nameList = [] #创建空列表
nameList = ['xiaoWang','xiaoZhang','xiaoHu']
testList = [1,'a'] #比c语言强大
2 列表元素访问
使用整数作为下标来访问其中的元素,下标为0的元素表示第1个元素,下标为-1的元素表示最后一个元素,以此类推
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
nameList = ['xiaoWang','xiaoZhang','xiaoHu']
#第一种遍历:
for name in nameList: #for循环遍历列表
print(name)
#第二种遍历:
length = len(nameList) #列表长度
i = 0 #Python中第一个字符是从0开始
while i<length:
print(nameList[i])
i+=1
#访问某个元素
print(nameList[0])
print(nameList[-1])
3 列表常用方法
1
2
3
4
A = ['xiaoWang','xiaoZhang','xiaoHua']
print('===操作之前,列表A的数据===')
for tempName in A:
print(tempName)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#1.添加元素 :三种,都属于原地操作,不影响列表对象在内存中的起始地址
#list.append() 在末尾添加
temp = input('请输入要添加的姓名:')
A.append(temp)
print('===操作之后,列表A的数据===')
for tempName in A:
print(tempName)
#extend 可以将另一个集合中的元素逐一添加到列表中
a = [1,2]
b = [3,4]
a.extend(b) #a=[1,2,3,4]
#insert(index,object) 在指定位置index前插入元素object
a = [0,1,2]
a.insert(1,3)#在下标为1的位置前插入元素 3
print(a)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#2.删除元素 也是原地操作
#del 根据下标进行删除
del moveName[2] # 删除下标为2 的元素的值
#pop() 删除最后一个元素
moveName.pop # 删除末尾
#remove() 根据元素的值进行删除
moveName.remove('指环王') # 删除 指环王
#clear()
x = [1,2,3]
x.clear() # 清空列表所有元素
1
2
3
4
5
#3.修改元素 原地操作
A = ['1','g','f','9']
A[1] = 'hahaha'
print(A)
1
2
3
4
5
6
7
#4.查找元素
#in 或者 not in
if findName in namelist:
print("找到啦哈哈哈")
else:
print("没找到呜呜呜")
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
#5.其他常见列表操作函数:
#index()
m.index(A) #输出元素A在列表m里面的索引位置号
m.index(A,a,b) #对于列表m里面包含多个元素A时,输出在列表m索引号a-b之间的特定索引号
a = ['f','a','b','c','a','b']
a.index('a',2,5) #左闭右开 在第2到4个位置找到a 发现在第4个位置 返回4
#----------------------------------------------------------------------------------------------------------------------
#count() 返回列表中指定元素出现次数
a.count('a')
#len() 返回列表长度
len(a)
#sort() reverse()
a = [1,4,2,3]
a.reverse() #将list逆置
print(a)
a.sort() #将list按特定顺序默认为从小到大, 参数reverse=Ture 可改为倒序 即由大到小 a.sort(reverse=True)
print(a)
#sorted()
#sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。
#list 的 sort 方法返回的是对已经存在的列表进行操作,无返回值,而内建函数 ;sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。
a = [5,7,6,3,4,1,2]
b = sorted(a) # 保留原列表
#a=[5, 7, 6, 3, 4, 1, 2]
#b=[1, 2, 3, 4, 5, 6, 7]
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
#6. copy() 浅复制
#深复制与浅复制
#浅复制是指生成一个新的列表,并且把源列表中所有元素的引用都复制到新列表中,当原列表只包含 整数、实数、复数、元组、字符串这样的不可变类型的数据,没问题。但是如果是包含列表之类的可变数据类型,浅复制只是把列表的引用复制到新列表中,修改任何一个都会影响另一个。
x = [1,2[3,4]]
y = x.copy()
print(y) #[1,2,[3,4]]
y[2].append(5) #y=[1, 2, [3, 4, 5]]
x[0] = 6 #x=[6,2,[3,4,5]]
y.append(6) #y=[1, 2, [3, 4, 5],6]
#deepcopy() 深复制:指对原列表中的元素进行递归,把所有的值都复制到新列表中,对嵌套的子列表不再是复制引用,这样两个列表相互独立,修改任何一个都互不影响。
import copy
x = [1,2,[3,4]]
y = copy.deepcopy(x)
x[2].append(5)
y.append(6) #y=[1,2,[3,4],6] x=[1,2,[3,4,5]]
#还有一种情况 对x做任何修改y都会受到影响
x = [1,2,[3,4]]
y = x
x[2].append(5)
x.append(6)
x[0] = 7 #x=[7,2,[3,4,5],6] y=[7,2,[3,4,5],6]
4 列表对象支持的运算符 加法运算符’+‘也可以实现列表增加元素的目的,但是这个运算符不属于原地操作,而是返回新列表,并且涉及大量元素的复制,效率低,使用’+=‘属于原地操作,与append()方法一样高效。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
x = [1,2,3]
print(id(x)) #原始id
x = x + [4] #连接两个列表
print(x)
print(id(x)) #内存地址发生变化
x += [5] #为列表追加元素
print(x)
print(id(x)) #与之前的原始id一样
#--------------------------------------------------------------------------------------------
x = [1,2,3,4]
x = x*2 #元素重复,返回新列表 x=[1,2,3,4,1,2,3,4]
x *= 2
#--------------------------------------------------------------------------------------------
#比较 >,< 主要进行数据型列表的元素比较
#and 逻辑运算符,可以进行列表之间的逻辑判断
5 内置函数对列表的操作
函数 | |
---|---|
max() | |
min() | |
sum() | |
len() | |
zip() | 多个列表中元素重新组合为元组并返回包含这些元组的zip对象 |
map() | 把函数映射到列表上的每个元素 |
6 列表模拟向量运算
1
2
x = [1,2,3] + [4,5,6]
print(x) # x=[1,2,3,4,5,6]
7 列表推导式
1
2
3
4
5
6
7
8
aList = [x*x for x in range(10)]
print(aList) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
vec = [[1,2,3],[4,5,6],[7,8,9]]
[num for elem in vec for num in elem] #[1, 2, 3, 4, 5, 6, 7, 8, 9]
matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
[[row[i] for row in matrix] for i in range(4)] #[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
8 切片的强大功能 [start:end:step]
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
30
31
32
33
34
35
36
37
38
39
40
41
42
#1. 使用切片获取列表部分元素
aList = [3,4,5,6,7,9,11,13,15,17]
aList[::] #start默认为0 step默认为1 可以不写
aList[::-1] #反向切片 [17, 15, 13, 11, 9, 7, 6, 5, 4, 3]
aList[::2] #[3,5,7,11,15]
aList[1::2] #[4,6,9,13,17]
aList[3:6] #[6,7,9]
aList[3:-10:-1] # 位置3在位置-10的右侧 -1表示反向切片 [6,5,4]
aList[3:-5] #位置3在位置-5的左侧,正向切片 [6,7]
#2. 使用切片为列表增加元素
aList = [3,5,7]
aList[len(aList):] = [9] #尾部增加元素9
aList[:0] = [1,2] #头部插入多个元素
aList[3:3] = [4] #中间插入元素
#3. 使用切片替换和修改列表中的元素
aList = [3,5,7,9]
aList[:3] = [1,2,3] #替换列表元素,等号两边的列表长度相等 [1,2,3,9]
aList[3:] = [4,5,6] #切片连续,等号两边的列表长度可以不相等 [1,2,3,4,5,6]
aList[::2] = [0] * 3 #各一个修改一个 [0,2,0,4,0,6]
#4. 使用切片删除列表中的元素
aList = [3,5,7,9]
aList[:3] = [] #删除列表中前3个元素 [9]
aList = [3,5,7,9,11]
del aList[:3] #[9,11]
aList = [3,5,7,9,11]
del aList[::2] #[5,9]
#5. 切片得到的是浅复制
aList = [3,5,7]
bList = aList[::]
aList == bList #True 两列表值相等
aList is bList #False 浅复制 不是同一个对象
id(aList) == id(bList) #False 两个列表对象的地址不相等
bList[1] = 8
print(bList) #[3,8,7]
print(aList) #[3,5,7] 修改bList 不影响aList
9 列表嵌套 list元素也可以是另一个list,比如:
1
2
3
s = ['python', 'java', ['asp', 'php'], 'scheme']
len(s)
#还可以是元组,字典等