Python 数据结构 1.零基础复习
目录
一、输入与输出
1.输入
2.格式化输出
二、数字与变量
1.字符串 & 整型
2.字符串 & 整型 & 浮点型
3.变量
练习 2235. 两整数相加
三、运算与操作
1.四则运算
练习 2769. 找出最大的可达成数字
3.取整与取余
练习 2651. 计算列车到站时间
编辑
四、真与假
1.布尔数
2.比较运算
Ⅰ、字符串的比较
Ⅱ、浮点数和整数比较
3.逻辑运算
练习 2396. 严格回文的数字
思路与算法
练习 2236. 判断根结点是否等于子结点之和
编辑
五、简单判断
1.判断语句
2.判断条件
3.空值与非空
4.代码块
练习 2651. 计算列车到站时间
六、复杂判断
1.if-else 双向判断
2.elif 多向判断
elif 多向判断
练习 2413. 最小偶倍数
七、列表
1.列表的定义
2.列表的基本特性
3.创建列表
Ⅰ、使用方括号创建列表
Ⅱ、使用 list() 构造函数创建列表
4.访问列表元素
Ⅰ、使用索引访问
Ⅱ、切片操作
5.修改列表
Ⅰ、添加元素
Ⅱ、修改元素
Ⅲ、删除元素
6.列表的其他方法
Ⅰ、查找元素
Ⅱ、排序
Ⅲ、反转
Ⅳ、列表推导式
Ⅴ、嵌套列表
7.列表与元组的区别
练习 LCR 182. 动态口令
练习 1929. 数组串联
八、for循环
1.了解for循环
2.代码执行顺序
3.遍历
练习 LCP 06. 拿硬币
4.range整数列表
5.累加
6.计数器
7.循环中 if 判断的应用
练习 2798. 满足目标工作时长的员工数目
练习 LCP 01. 猜数字
练习 778. 特殊元素平方和
九、while循环
1.while循环
2.for和while循环的区别
3.死循环
练习 1295. 统计位数为偶数的数字
4.循环中断 break
5.循环中断 continue
练习 1470. 重新排列数组
编辑
练习 1920. 基于排列构建数组
练习 2824. 统计和小于目标的下标对数目
练习 1365. 有多少小于当前数字的数字
编辑
练习 2176. 统计数组中相等且可以被整除的数对
十、元组
1.元组的定义
元组的创建方法
2.元组的基础特性
3.元组的运算
元组的解包
成员检查
4.元组的删除
十一、字典
1.字典的定义
字典的创建方法
2.查找字典元素
3.增加字典元素
4.删除字典元素
5.常用方法
练习 2351. 第一个出现两次的字母
练习 1512. 好数对的数目
解法 ①
解法 ②
6.字典的高级应用场景
7.数据结构小结
列表、元组、字典的常见报错
十二、函数使用
1.函数的定义
2.函数的调用
练习.1732. 找到最高海拔
3.函数名
4.函数参数
5.函数返回值
6.函数必选参数
7.函数默认参数
8.函数不定长参数
9.函数执行顺序
10.Python中的一些内置函数
十三、类
1.类的定义
2.类的属性
3.类的方法
十四、类和对象
1.对象
2.实例化
3.面向对象编程
十五、类和函数共性
1.封装
2.变量作用域
3.跳转
新的一年,一定会有新的奇迹发生
—— 25.2.28
一文速通 复习 & 回顾 & 精炼 Python基础语法
一、输入与输出
输入:我们在计算机上输入一些字符,用绘图板给计算机绘制一些图形,这些计算机收到的来自“外界”的数据传递,叫做输入
输出:我们通过编程让计算机在屏幕上显示一张图,一行字,这些计算机对“外界”的数据传递,都叫做输出
1.输入
print():中英文敏感,引号和括号都应用英文符
代码:程序员用某种编程语言写出来的文本,可以被计算机一行行执行
print("Hello World!")
2.格式化输出
在编程中,格式化输出是指按指定的格式输出数据
包括控制输出的格式精度、小数位数,以便更好的展示和处理数据
格式化输出通常使用占位符和格式说明符来指定输出的内容和格式
Python中输出模板信息的方法,叫做格式化输出,可以实现灵活输出字符串,并能修改其中的变量
格式化输出让我们可以灵活的进行字符串的打印
print(f"欢迎{name}参加我的生日会")
二、数字与变量
在编程中整数和浮点数是两种基础的数据类型
整数如 5、-3、(是没有小数部分的数字)
浮点数如 3.14、-0.99是有包含小数部分的数字
编程中表示数字的是整形(int)和浮点型(float)
整型(integer):整数
浮点型(floating-point):小数
1.字符串 & 整型
编程中用来表示整数的型状叫做整型,包括正数、负数、零
和字符串不同,整型是不需要用引号的
可以简单的理解为,整型就是编程世界里的整数
2.字符串 & 整型 & 浮点型
编程中用来表示小数的类型叫做浮点型。
它和整型的相似点在于,都不需要用引号(只有字符串才需要)。
不同点是,浮点型有一个小数点。
同样的,我们也可以简单的记住,浮点型就是编程世界里的小数
3.变量
在 Python 中,变量是用来存储信息的实体数字、字符串或更复杂的数据结构变量有有己的名称
我们可以通过这个名称访问储存在变量里的信息也可以改变其存储的信息值
变量可以用来存储各式各样的数据,存储的数据是可以变化的,所以叫做变量
我们可以把变量想象一个盒子,它里面可以装各式各样的数据。因为这个“盒子”里存储的数据是“可以变化的”,所以我们叫他变量。
变量的名字有自己的命名规则,它可以由字母、数字、下划线(_)组成,但是,它不能以数字开头。
python中的变量命名有一些风格,我们鼓励google的变量命名风格,即所有变量只使用小写字母和下划线,单词和单词之间用下划线连接。
练习 2235. 两整数相加
给你两个整数
num1
和num2
,返回这两个整数的和。示例 1:
输入:num1 = 12, num2 = 5 输出:17 解释:num1 是 12,num2 是 5 ,它们的和是 12 + 5 = 17 ,因此返回 17 。示例 2:
输入:num1 = -10, num2 = 4 输出:-6 解释:num1 + num2 = -6 ,因此返回 -6 。提示:
-100 <= num1, num2 <= 100
class Solution:
def sum(self, num1: int, num2: int) -> int:
return num1 + num2
三、运算与操作
1.四则运算
在编程中四则运算包括加、减、乘、除,这些操作可以对整数、浮点数等数据类型进行计算,用于构建复杂的算法和函数
加(+)、减(-)、乘(*)、除(/)
字符串操作
字符串之间可以通过 + 号进行拼接,形成新的字符串
需要注意的是,不能把数字(整型/浮点型)与字符串之间使用加号+拼接,这会导致程序报错
无论是用整型还是浮点型进行处除法/运算,计算结果一定是一个浮点型
对于四则运算来说,我们可以记住参与计算的有浮点型的话,结果一定是浮点型;参与计算是整型的话,结果一定是整型(除法例外)
练习 2769. 找出最大的可达成数字
给你两个整数
num
和t
。如果整数x
可以在执行下述操作 不超过t
次的情况下变为与num
相等,则称其为 可达成数字 :每次操作将
x
的值增加或减少1
,同时可以选择将num
的值增加或减少1
。返回所有可达成数字中的 最大 值
x
。示例 1:
输入:num = 4, t = 1
输出:6
解释:
执行下述操作可以使最大可达成数字等于
num
:最大可达成数字减少 1 ,同时
num
增加 1 。示例 2:
输入:num = 3, t = 2
输出:7
解释:
执行两次下述操作可以使最大可达成数字等于 num :
最大可达成数字减少 1 ,同时
num
增加 1。
class Solution:
def theMaximumAchievableX(self, num: int, t: int) -> int:
return num + 2 * t
3.取整与取余
在编程中,取整是指无论小数部分是多少都只保留整数部分
取余是当一个数除以另一个数后余下的部分
10除以3等于3余1所以取整结果是3,取余结果是1
除了传统的四则运算,Python还可以进行求商和求余数的运算
取整运算符 //,它用来求商,10除以3,商是3,余数是1,计算结果就是3
取整数商的应用场景很多,例如在游戏开发中,取整操作可以用于处理游戏物体的位置和运动,确保游戏物体运动的更加平滑和自然
取模运算符 %,它用来求余数,10除以3,因为商是3,余数是1,计算结果就是1
取模运算符的效率会比减法运算符的效率偏低,我们要慎重使用
练习 2651. 计算列车到站时间
给你一个正整数
arrivalTime
表示列车正点到站的时间(单位:小时),另给你一个正整数delayedTime
表示列车延误的小时数。返回列车实际到站的时间。
注意,该问题中的时间采用 24 小时制。
示例 1:
输入:arrivalTime = 15, delayedTime = 5 输出:20 解释:列车正点到站时间是 15:00 ,延误 5 小时,所以列车实际到站的时间是 15 + 5 = 20(20:00)。示例 2:
输入:arrivalTime = 13, delayedTime = 11 输出:0 解释:列车正点到站时间是 13:00 ,延误 11 小时,所以列车实际到站的时间是 13 + 11 = 24(在 24 小时制中表示为 00:00 ,所以返回 0)。提示:
1 <= arrivaltime < 24
1 <= delayedTime <= 24
class Solution:
def findDelayedArrivalTime(self, arrivalTime: int, delayedTime: int) -> int:
return (arrivalTime + delayedTime) % 24
四、真与假
1.布尔数
在编程中,布尔数是用于表示逻辑值的一种数据类型,它只有两个值:真和假
布尔数常用于条件判断,逻辑运算等操作
在编程中,我们用 True 和 False 来表达 真 和 假 这两种状态,首字母需要大写,他们又叫布尔数
True 和 False 都是常量,所以我们可以把他们赋值给一个变量
2.比较运算
在编程中,比较运算是一种基本运算,用于比较两个数值或字符串的大小关系,比较运算的结果,通常是一个布尔值用于判断条件是否成立
比较运算:>、<、>=、<=、==、!=
在编程中,我们会使用数学符号来进行比较运算,比如比较两个数的大小
等于符号(==) 和 不等于符号(!=)
赋值符号是一个等号,作用是把一个数据装入变量;
等于符号是两个等号,作用是比较两个数是否相等。
Ⅰ、字符串的比较
字符串之间可以使用等于(==)和不等于(!=)来比较这两个字符串是否一样
Ⅱ、浮点数和整数比较
浮点数和整数也是可以进行比较的
3.逻辑运算
在编程中,逻辑运算指的是对逻辑关系进行运算和处理的操作
它用于判断条件是否满足,确定程序执行路径等
常见的逻辑运算符包括与(and)、或(or)、非(not)它们用于组合和比较条件以实现程序的逻辑控制
and又叫“与运算”,假设你是一个28岁的女生,那么“你28岁”并且“你是女生”,这句话表述就是真的,但是“你28岁”并且“你是男生”,这句表述就是假的
and运算需要参与运算的两个条件都为真,结果才是真;有一个为假,结果就是假。
or又叫“或运算”,假设你是一个28岁的女生,那么“你28岁”或者“你是男生”,虽然前一句是真,后一句是假,但这个表述也为真。这时候只有“你不是28岁”或者“你是男生”这句表述是假的 。因为前一句和后一句都是假的。
or运算只要参与运算的其中一个条件为真,就为真。除非两个条件都为假,才是假。
not运算又叫“否运算”,假设你28岁,那么“你不是28岁”就是个假的表述,“你不是10岁”就是个真的表述。
not运算里面,not真为假,not假为真
练习 2396. 严格回文的数字
如果一个整数
n
在b
进制下(b
为2
到n - 2
之间的所有整数)对应的字符串 全部 都是 回文的 ,那么我们称这个数n
是 严格回文 的。给你一个整数
n
,如果n
是 严格回文 的,请返回true
,否则返回false
。如果一个字符串从前往后读和从后往前读完全相同,那么这个字符串是 回文的 。
示例 1:
输入:n = 9 输出:false 解释:在 2 进制下:9 = 1001 ,是回文的。 在 3 进制下:9 = 100 ,不是回文的。 所以,9 不是严格回文数字,我们返回 false 。 注意在 4, 5, 6 和 7 进制下,n = 9 都不是回文的。示例 2:
输入:n = 4 输出:false 解释:我们只考虑 2 进制:4 = 100 ,不是回文的。 所以我们返回 false 。提示:
4 <= n <= 105
思路与算法
在题目的条件下,答案一定为 false,证明如下:
根据带余除法,n=qb+r,其中 0≤r<b。
取 b=n−2,那么当 n>4 时,上式的 q=1,r=2,也就是说 n 在 n−2 进制下的数值为 12,不是回文数。
而对于 n=4,在 b=2 进制下的数值为 100,也不是回文数。
因此直接返回 false 即可。
class Solution:
def isStrictlyPalindromic(self, n: int) -> bool:
return False
练习 2236. 判断根结点是否等于子结点之和
给你一个 二叉树 的根结点
root
,该二叉树由恰好3
个结点组成:根结点、左子结点和右子结点。如果根结点值等于两个子结点值之和,返回
true
,否则返回false
。示例 1:
输入:root = [10,4,6] 输出:true 解释:根结点、左子结点和右子结点的值分别是 10 、4 和 6 。 由于 10 等于 4 + 6 ,因此返回 true 。示例 2:
输入:root = [5,3,1] 输出:false 解释:根结点、左子结点和右子结点的值分别是 5 、3 和 1 。 由于 5 不等于 3 + 1 ,因此返回 false 。提示:
- 树只包含根结点、左子结点和右子结点
-100 <= Node.val <= 100
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def checkTree(self, root: Optional[TreeNode]) -> bool:
return root.val == root.left.val + root.right.val
五、简单判断
在编程中,if 语句是一种用于根据条件执行不同代码块 的 控制结构,它根据特定条件的真假来分支程序的执行路径。通过使用 if 语句,程序可以根据不同的情况执行不同的操作,从而实现逻辑判断和条件处理
布尔数用在什么地方呢?它可以用在代码中判断语句的判断条件,帮助我们进行判断,进而决定执行那些代码
1.判断语句
这种在代码中根据不同的条件,执行不同代码的结构,我们叫它“判断语句”
如果判断条件为真(True),我们就让程序执行某行代码;如果判断条件为假(False),就让程序不执行某行代码。
一个if判断是由关键字if,判断条件,冒号:和 “所属”代码构成的
需要注意的是,关键字 if 和 判断条件 之间有个空格
if 是python中的关键字,是“如果”的意思,表明后面的条件如果成立,就会执行一些代码。
if 后面是一个判断条件。 if 语句仅在结果为真(True )时执行归属于if的代码。尝试在输入
框填入 True,如果判断条件的结果为假(False ),归属于if的代码就不狯被执行,而会直接跳过
英文冒号 : 是 if 判断语句的固定格式,表示该句代码的结束
在判断的归属代码前需要有四个空格,这四个空格的作用是用来告诉计算机:这些代码归属于这个if判断语句
2.判断条件
在编程中,if 语句中的判断条件决定了 if 语句是否执行,这个条件可以是布尔数、比较运算 或者 逻辑运算等等
if 后跟随判断条件,判断条件本质上是看它是 真(True) 还是 假(False),它既可以直接是个布尔数(比如前面提到的代码案例);也可以是一个比较运算或者逻辑运算,因为它们的运算结果也是一个True 或者 False
在 if 判断中,我们知道了如果判断条件是 True ,就会执行它“所属”的代码;如果判断条件是False ,就不会执行。除了直接使用布尔数 True 和 False,我们还可以使用运算结果是布尔数的一些“条件”,比如比较运算 5 >3,它的运算结果是True,这时 if 判断也会执行代码。
除了比较运算,逻辑运算也能得到一个True/False的布尔数,因为逻辑运算也经常被用作判断的条件。
需要注意的是,判断条件涉及到的比较运算和逻辑运算,默认是从左到右计算的,除非有括号,括号里的需要最先计算(如图中的①②③执行顺序)
当然作为代码风格的一部分,我们建议把每个单独有实际意义的运算,都用括号括起来
3.空值与非空
在编程中,空值指没有任何值或未赋值的状态,非空则指变量已被赋予某些值,即该变量包含有效数据或信息
如果一个变量是有数据的,在Python中这个变量就等价于True
关键字 None 代表空值,就是什么都没有。作为判断条件,空值等价于False,所以if判断语句内的
代码不会执行。
除了空值None以外,其他只要有数据的值,都是非空值,比如所有的常量数值,包括整型,浮点型,字符
我们可以简单的理解为,当判断条件是一个变量或者常量的时候,如果它是一个有具体数据的非空值,那么它等价于 True ;如果它是一个没有具体数据的空值的时候,那么它等价于 False
4.代码块
代码块,是编程中一组按逻辑组织的语句,它可以组合控制结构如循环和条件语句进行具体的操作Python里的缩进(Indentation)是四个空格,同样缩进四个空格的代码块,属于同一个层级
同样缩进的代码属于同一层级,下一级缩进的代码“从属于”上一级,比如第二行代码就“从属于”第一行的条件判断
if 判断后的判断条件为True,则程序执行归属于if 判断的一个代码块。缩进就是为了组织代码块(Code Block),区分代码的层级
同一层级(即同样缩进四个空格)的代码集合叫做代码块(Code Block),代码块中的代码会按照由上至下的顺序执行
练习 2651. 计算列车到站时间
给你一个正整数
arrivalTime
表示列车正点到站的时间(单位:小时),另给你一个正整数delayedTime
表示列车延误的小时数。返回列车实际到站的时间。
注意,该问题中的时间采用 24 小时制。
示例 1:
输入:arrivalTime = 15, delayedTime = 5 输出:20 解释:列车正点到站时间是 15:00 ,延误 5 小时,所以列车实际到站的时间是 15 + 5 = 20(20:00)。示例 2:
输入:arrivalTime = 13, delayedTime = 11 输出:0 解释:列车正点到站时间是 13:00 ,延误 11 小时,所以列车实际到站的时间是 13 + 11 = 24(在 24 小时制中表示为 00:00 ,所以返回 0)。提示:
1 <= arrivaltime < 24
1 <= delayedTime <= 24
class Solution:
def findDelayedArrivalTime(self, arrivalTime: int, delayedTime: int) -> int:
if arrivalTime + delayedTime >= 24:
return arrivalTime + delayedTime -24
else:
return arrivalTime + delayedTime
六、复杂判断
1.if-else 双向判断
在编程中,if-else 是一种基本的控制结构
用于根据条件的真假,执行不同的代码块,if 后的条件为真时,执行特定操作;否则执行 else 后的操作
两段代码表达了一样的意思,但第二种写法更加简洁,它只需要一个关键字 else 就可以了
if-else 判断结构由关键字 else和英文冒号 : 构成
else 是和 if 配对的关键词,else 无法单独出现,它的前面一定有一个跟它配对的 if
if 的条件成立的话,if 内部的代码块会被执行,而 else 的作用就是,如果 if 的条件不成立,那么else 内部的代码块就会被执行,它们之间的关系就类似于汉语中的“如果-否则”
为什么 else 不需要像 if 一样后面跟一个判断条件呢?这是因为 else 囊括了所有 if 条件以外的条件:只要 if 判断的条件不成立,就会进入 else 的范畴。
else 只会跟最近的一个 if 进行配对,所以我们可以看到这段代码输出了两句话:“周四吃肯德鸡” 和 “周四随便吃吃”。因为第一个 if 判断是成立的,所以输出了第一句话:第二个 if 判断是不成立的,所以这里进入了 else 的代码分支,又输出了第二句话
2.elif 多向判断
在编程中,elif 是 else if 的简写,用于在 if 语句之后,添加额外的条件判断
如果 if 语句的条件为假,那么程序将检查 elif 语句的条件
这种有三个或者更多的判断条件的情况,代码中也有对应的处理机制,那就是 elif 关键字,这个关键字是 else if 的缩写。我们可以看到,使用 elif 以后,判断条件变得更简洁了。
使用三个 if 的时候,我们需要对三个 if 判断的条件都做清晰的界定;但是使用 if-elif-else 判断结构的时候,我们只需要对前两个的判断条件做清晰的界定,除此以外的所有情况,都在else里面执行。
elif 多向判断
在 if-elif-else 的判断中,elif 后面也有判断条件和固定语法格式:
if score >= 90:
print("成绩等级:A")
elif score >= 80:
print("成绩等级:B")
elif score >= 70:
print("成绩等级:C")
elif score >= 60:
print("成绩等级:D")
else:
print("成绩等级:F")
elif 语句由三部分构成,关键字 elif,具体的判断条件,英文冒号 :
if、elif 、else 三者是独立互斥的关系,就是说,程序只会执行其中一个分支的代码块。要么执行 if 的代码块,要么执行 elif 的代码块,如果前两个条件都不符合,就执行else的代码块。
当判断的条件超过3个时,中间的多个条件都可以使用 elif
练习 2413. 最小偶倍数
给你一个正整数
n
,返回2
和n
的最小公倍数(正整数)。示例 1:
输入:n = 5 输出:10 解释:5 和 2 的最小公倍数是 10 。示例 2:
输入:n = 6 输出:6 解释:6 和 2 的最小公倍数是 6 。注意数字会是它自身的倍数。提示:
1 <= n <= 150
class Solution:
def smallestEvenMultiple(self, n: int) -> int:
return n if n % 2 == 0 else n * 2
七、列表
1.列表的定义
Python 列表(List)是一种有序、可变且允许重复元素的数据结构。列表使用方括号 []
表示,元素之间用逗号 ,
分隔。列表是 Python 中最常用的数据结构之一,适用于存储和管理一系列项目。
变量就像一个盒子,可以装各种东西,但一次只能装1种;
而列表就像收纳盒,可以有序地在每一个盒子中,装上不同的东西。
列表中的元素,可以是数字、字符串、字符串和数字混合,甚至嵌套列表(列表中有列表)。
2.列表的基本特性
有序:列表中的元素按照插入顺序排列,可以通过索引(索引是在数据结构中用来定位和寻找数据的检索方式)访问。在存储的过程中,每一项元素都有固定的位置,方便查找和修改列表中的元素
可变:可以在创建后添加、删除或修改列表中的元素。
允许重复:列表中可以包含重复的元素。
异构:列表中的元素可以是不同类型的,如整数、字符串、浮点数、其他列表等。
3.创建列表
Ⅰ、使用方括号创建列表
# 创建一个空列表
empty_list = []
# 创建一个包含多个元素的列表
fruits = ['apple', 'banana', 'cherry']
# 创建一个包含不同类型元素的列表
mixed_list = [1, 'apple', 3.14, True]
Ⅱ、使用 list()
构造函数创建列表
# 从字符串创建列表
char_list = list('hello')
print(char_list) # 输出: ['h', 'e', 'l', 'l', 'o']
# 从元组创建列表
tuple_data = (1, 2, 3)
list_from_tuple = list(tuple_data)
print(list_from_tuple) # 输出: [1, 2, 3]
4.访问列表元素
Ⅰ、使用索引访问
索引是在数据结构中用来定位和寻找数据的检索方式
正索引:从左到右,索引从 0
开始。
负索引:从右到左,索引从 -1
开始。
Ⅱ、切片操作
列表切片是从原始列表中提取列表的一部分的过程
左闭右开的区间,取左不取右,元素数 = 冒号右边数字 - 冒号左边数字
开始位置数字不填,默认从第一个元素开始切片
结束位置数字不填,默认取到最后一个元素
开始和结束位置数字都不填,[:] 默认取出所有元素
fruits = ['apple', 'banana', 'cherry', 'date', 'elderberry']
# 获取前三个元素
first_three = fruits[:3]
print(first_three) # 输出: ['apple', 'banana', 'cherry']
# 获取第三个到第五个元素
middle = fruits[2:5]
print(middle) # 输出: ['cherry', 'date', 'elderberry']
# 获取从第三个元素开始到末尾
from_third = fruits[2:]
print(from_third) # 输出: ['cherry', 'date', 'elderberry']
5.修改列表
Ⅰ、添加元素
append()
:在列表末尾添加一个元素。
extend()
:在列表末尾添加多个元素(通常是一个可迭代对象)。
insert()
:在指定位置插入一个元素。插入元素可以理解为:你想把这个新元素放到第几位,括号中就要填上对应的索引位置,后面的元素都会给新来的元素让位,插入的元素可以是不同数据类型,包括:字符串、整型、浮点型、元组以及列表等
fruits = ['apple', 'banana']
# 添加一个元素
fruits.append('cherry')
print(fruits) # 输出: ['apple', 'banana', 'cherry']
# 添加多个元素
fruits.extend(['date', 'elderberry'])
print(fruits) # 输出: ['apple', 'banana', 'cherry', 'date', 'elderberry']
# 在指定位置插入元素
fruits.insert(1, 'blueberry')
print(fruits) # 输出: ['apple', 'blueberry', 'banana', 'cherry', 'date', 'elderberry']
Ⅱ、修改元素
通过索引值直接修改元素
fruits = ['apple', 'blueberry', 'banana', 'cherry']
# 修改第二个元素
fruits[1] = 'blackberry'
print(fruits) # 输出: ['apple', 'blackberry', 'banana', 'cherry']
Ⅲ、删除元素
del
:删除指定索引的元素。
remove()
:删除第一个匹配的元素。
pop()
:删除并返回指定索引的元素,默认删除最后一个元素。
fruits = ['apple', 'blackberry', 'banana', 'cherry']
# 删除第二个元素
del fruits[1]
print(fruits) # 输出: ['apple', 'banana', 'cherry']
# 删除第一个 'banana'
fruits.remove('banana')
print(fruits) # 输出: ['apple', 'cherry']
# 删除并返回最后一个元素
last_fruit = fruits.pop()
print(last_fruit) # 输出: cherry
print(fruits) # 输出: ['apple']
6.列表的其他方法
Ⅰ、查找元素
index()
:返回第一个匹配元素的索引。
count()
:返回元素在列表中出现的次数。
fruits = ['apple', 'banana', 'cherry', 'banana']
# 查找 'banana' 的索引
index = fruits.index('banana')
print(index) # 输出: 1
# 统计 'banana' 出现的次数
count = fruits.count('banana')
print(count) # 输出: 2
Ⅱ、排序
sort()
:对列表进行原地排序。
sorted()
:返回一个新的排序后的列表,原列表不变。
fruits = ['banana', 'apple', 'cherry']
# 原地排序
fruits.sort()
print(fruits) # 输出: ['apple', 'banana', 'cherry']
# 返回一个新的排序后的列表
sorted_fruits = sorted(fruits)
print(sorted_fruits) # 输出: ['apple', 'banana', 'cherry']
print(fruits) # 输出: ['apple', 'banana', 'cherry']
Ⅲ、反转
reverse()
:原地反转列表。
reversed()
:返回一个迭代器。
fruits = ['apple', 'banana', 'cherry']
# 原地反转
fruits.reverse()
print(fruits) # 输出: ['cherry', 'banana', 'apple']
# 使用 reversed() 返回迭代器
for fruit in reversed(fruits):
print(fruit)
# 输出:
# apple
# banana
# cherry
Ⅳ、列表推导式
# 创建一个包含0到9的平方的列表
squares = [x**2 for x in range(10)]
print(squares) # 输出: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# 过滤出偶数的平方
even_squares = [x**2 for x in range(10) if x % 2 == 0]
print(even_squares) # 输出: [0, 4, 16, 36, 64]
Ⅴ、嵌套列表
列表中包含其他列表,形成嵌套结构
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
# 访问第二行第三列的元素
element = matrix[1][2]
print(element) # 输出: 6
7.列表与元组的区别
列表和元组都是序列类型
特性 | 列表 (List) | 元组 (Tuple) |
---|---|---|
可变性 | 可变 | 不可变 |
语法 | 使用方括号 [] | 使用圆括号 () |
性能 | 由于可变性,操作较慢 | 由于不可变性,操作较快 |
适用场景 | 需要频繁修改的数据集合 | 不需要修改的数据集合,如函数返回多个值 |
练习 LCR 182. 动态口令
某公司门禁密码使用动态口令技术。初始密码为字符串
password
,密码更新均遵循以下步骤:
- 设定一个正整数目标值
target
- 将
password
前target
个字符按原顺序移动至字符串末尾请返回更新后的密码字符串。
示例 1:
输入: password = "s3cur1tyC0d3", target = 4 输出: "r1tyC0d3s3cu"示例 2:
输入: password = "lrloseumgh", target = 6 输出: "umghlrlose"提示:
1 <= target < password.length <= 10000
class Solution:
def dynamicPassword(self, password: str, target: int) -> str:
return password[target:] + password[:target]
练习 1929. 数组串联
给你一个长度为
n
的整数数组nums
。请你构建一个长度为2n
的答案数组ans
,数组下标 从 0 开始计数 ,对于所有0 <= i < n
的i
,满足下述所有要求:
ans[i] == nums[i]
ans[i + n] == nums[i]
具体而言,
ans
由两个nums
数组 串联 形成。返回数组
ans
。示例 1:
输入:nums = [1,2,1] 输出:[1,2,1,1,2,1] 解释:数组 ans 按下述方式形成: - ans = [nums[0],nums[1],nums[2],nums[0],nums[1],nums[2]] - ans = [1,2,1,1,2,1]示例 2:
输入:nums = [1,3,2,1] 输出:[1,3,2,1,1,3,2,1] 解释:数组 ans 按下述方式形成: - ans = [nums[0],nums[1],nums[2],nums[3],nums[0],nums[1],nums[2],nums[3]] - ans = [1,3,2,1,1,3,2,1]提示:
n == nums.length
1 <= n <= 1000
1 <= nums[i] <= 1000
class Solution:
def getConcatenation(self, nums: List[int]) -> List[int]:
return nums + nums
class Solution:
def getConcatenation(self, nums: List[int]) -> List[int]:
nums.extend(nums)
return nums
八、for循环
1.了解for循环
循环是一种控制流结构,两种常见的循环是:for循环 和 while循环,用于处理定量和无限任务
自然界中,一直重复的四季更替,昼夜交替,阴晴圆缺叫做循环。在程序中,满足条件的情况下,重复执行同一段代码就叫做循环
2.代码执行顺序
代码执行顺序是一个很重要的概念,关系着你在排查错误的时候,按照什么样的顺序去查代码常见的代码执行顺序有:顺序、选择、循环、跳转
3.遍历
遍历指的是依次访问某个数据结构中的每一个元素,通常使用 for 或者 while 进行遍历
除了遍历列表,for循环还可以遍历字符串,并逐个获取字符串的每个字符在输入框中填入变量 word 查看输出结果。
练习 LCP 06. 拿硬币
桌上有
n
堆力扣币,每堆的数量保存在数组coins
中。我们每次可以选择任意一堆,拿走其中的一枚或者两枚,求拿完所有力扣币的最少次数。示例 1:
输入:
[4,2,1]
输出:
4
解释:第一堆力扣币最少需要拿 2 次,第二堆最少需要拿 1 次,第三堆最少需要拿 1 次,总共 4 次即可拿完。
示例 2:
输入:
[2,3,10]
输出:
8
限制:
1 <= n <= 4
1 <= coins[i] <= 10
class Solution:
def minCount(self, coins: List[int]) -> int:
n = 0
for i in coins:
if i % 2 == 0:
n = n + i // 2
else:
n = n + i // 2 + 1
return n
4.range整数列表
在 Python 中,range()用于生成一系列连续整数,它在循环和其他需要迭代的场景中特别有用
range()方法可以创建一个整数列表,一般用在 for 循环中。
声明:Python的版本不同,range()生成的格式不同,在Python2中是列表,Python3中是可迭代对象,用法是类似的。
当range()函数只填写1个参数时,range(a)表示生成的整数从0开始,到a结束且不包含a
当range()函数中填写2个数时,例如range(a,b),表示生成的整数从a开始,到b结束且不包含b
range()函数中填写3个参数时,range(a,b,c)表示生成的整数从a开始,到b结束且不包含b,整数之间的间隔为c,如果不填写,默认整数间隔为1
range(a, b, c)的三个参数,表示开始,结束和步长
开始:计数从a开始,默认是从0开始
结束:计数到b结束,但不包括b
步长:默认为1
5.累加
在编程中,累加指的是持续将某个值加到一个变量上,例如:在循环中你可能会设置一个累加器变量然后在每次选代时增加某个值
for循环可以实现数字的累加,累加的过程如下:
total = 0
for i in range(101):
total = total + i
print(total)
6.计数器
在编程中,计数器常用于在循环中追踪已经执行了多少次迭代,通常会初始化一个计数器变量,然后在每次循环时将其递增
for循环中使用if语句时,要注意缩进。
第一个缩进,代表着for循环中的代码需要增加缩进,表明是一个代码块。
第二个缩进,使用if语句时,语句里面的内容也需要增加缩进
7.循环中 if 判断的应用
可以通过 for循环 结合 if判断,筛选需要的元素
练习 2798. 满足目标工作时长的员工数目
公司里共有
n
名员工,按从0
到n - 1
编号。每个员工i
已经在公司工作了hours[i]
小时。公司要求每位员工工作 至少
target
小时。给你一个下标从 0 开始、长度为
n
的非负整数数组hours
和一个非负整数target
。请你用整数表示并返回工作至少
target
小时的员工数。示例 1:
输入:hours = [0,1,2,3,4], target = 2 输出:3 解释:公司要求每位员工工作至少 2 小时。 - 员工 0 工作 0 小时,不满足要求。 - 员工 1 工作 1 小时,不满足要求。 - 员工 2 工作 2 小时,满足要求。 - 员工 3 工作 3 小时,满足要求。 - 员工 4 工作 4 小时,满足要求。 共有 3 位满足要求的员工。示例 2:
输入:hours = [5,1,4,2,2], target = 6 输出:0 解释:公司要求每位员工工作至少 6 小时。 共有 0 位满足要求的员工。提示:
1 <= n == hours.length <= 50
0 <= hours[i], target <= 105
class Solution:
def numberOfEmployeesWhoMetTarget(self, hours: List[int], target: int) -> int:
n = 0
for i in hours:
if i >= target:
n = n + 1
return n
练习 LCP 01. 猜数字
小A 和 小B 在玩猜数字。小B 每次从 1, 2, 3 中随机选择一个,小A 每次也从 1, 2, 3 中选择一个猜。他们一共进行三次这个游戏,请返回 小A 猜对了几次?
输入的
guess
数组为 小A 每次的猜测,answer
数组为 小B 每次的选择。guess
和answer
的长度都等于3。示例 1:
输入:guess = [1,2,3], answer = [1,2,3] 输出:3 解释:小A 每次都猜对了。示例 2:
输入:guess = [2,2,3], answer = [3,2,1] 输出:1 解释:小A 只猜对了第二次。限制:
guess
的长度 = 3answer
的长度 = 3guess
的元素取值为{1, 2, 3}
之一。answer
的元素取值为{1, 2, 3}
之一。
class Solution:
def game(self, guess: List[int], answer: List[int]) -> int:
sum = 0
for i in range(3):
if guess[i] == answer[i]:
sum = sum + 1
return sum
练习 778. 特殊元素平方和
给你一个下标从 1 开始、长度为
n
的整数数组nums
。对
nums
中的元素nums[i]
而言,如果n
能够被i
整除,即n % i == 0
,则认为num[i]
是一个 特殊元素 。返回
nums
中所有 特殊元素 的 平方和 。示例 1:
输入:nums = [1,2,3,4] 输出:21 解释:nums 中共有 3 个特殊元素:nums[1],因为 4 被 1 整除;nums[2],因为 4 被 2 整除;以及 nums[4],因为 4 被 4 整除。 因此,nums 中所有特殊元素的平方和等于 nums[1] * nums[1] + nums[2] * nums[2] + nums[4] * nums[4] = 1 * 1 + 2 * 2 + 4 * 4 = 21 。示例 2:
输入:nums = [2,7,1,19,18,3] 输出:63 解释:nums 中共有 4 个特殊元素:nums[1],因为 6 被 1 整除;nums[2] ,因为 6 被 2 整除;nums[3],因为 6 被 3 整除;以及 nums[6],因为 6 被 6 整除。 因此,nums 中所有特殊元素的平方和等于 nums[1] * nums[1] + nums[2] * nums[2] + nums[3] * nums[3] + nums[6] * nums[6] = 2 * 2 + 7 * 7 + 1 * 1 + 3 * 3 = 63 。提示:
1 <= nums.length == n <= 50
1 <= nums[i] <= 50
len():len()
函数通过调用对象的__len__()
方法获取长度,适用于序列(如字符串、列表、元组)和集合(如字典、集合)等可迭代对象
class Solution:
def sumOfSquares(self, nums: List[int]) -> int:
sum = 0
n = len(nums)
for i in range(n):
if n % (i + 1) == 0:
sum += nums[i] ** 2
return sum
九、while循环
1.while循环
在Python中,while循环是一种控制流语句,它允许一段代码特续执行,直到满足特定条件后停止这使我们能够有效地创建不定数量的选代
条件循环,又称while循环,以判断条件是否成立,来决定是否执行循环内的代码。当判断为True时,代码会循环执行,当判断为False时,则终止循环。
在while循环中,有一个判断条件,来决定是否执行循环内的代码。判断为True,则继续执行循环;判断为False,就会终止循环;这样的判断条件,就是边界条件。
2.for和while循环的区别
在大多数情况下,for循环和while循环可以互换使用
for循环在每一次循环的时候,是按照从头到尾的顺序自动遍历,给变量 i 赋值列表中的元素
while循环则没有构建列表而是通过在边界条件内,依次给变量 i 值加1,并输出实现。
也就是说,两种循环的终止条件不一样。for循环的终止条件是遍历完整个列表;while循环的终止条件是边界条件,也就是 i<3
3.死循环
循环虽然好用,但是不合理的边界条件设计会让计算机卡住,走不出循环
for 循环通常是对一个数据集合比如列表的遍历。数据集合的大小是固定的,所以循环次数是固定的,循环可以有始有终。
但 while 循环是通过循环条件来控制的,如果循环条件不满足,则会跳出循环;如果条件一直满足,就会一直执行,甚至出现死循环。
在编程中,一个靠自身无法终止的程序称为"死循环",死循环是一种循环类型,当一个循环永远无法终止的时候,我们就说它是一个死循环。就像是困在没有出口的密室,只能一直在里面循环无法逃脱。
练习 1295. 统计位数为偶数的数字
给你一个整数数组
nums
,请你返回其中位数为 偶数 的数字的个数。示例 1:
输入:nums = [12,345,2,6,7896] 输出:2 解释: 12 是 2 位数字(位数为偶数) 345 是 3 位数字(位数为奇数) 2 是 1 位数字(位数为奇数) 6 是 1 位数字 位数为奇数) 7896 是 4 位数字(位数为偶数) 因此只有 12 和 7896 是位数为偶数的数字示例 2:
输入:nums = [555,901,482,1771] 输出:1 解释: 只有 1771 是位数为偶数的数字。提示:
1 <= nums.length <= 500
1 <= nums[i] <= 105
class Solution:
def findNumbers(self, nums: List[int]) -> int:
sum = 0
for i in nums:
num = 0
while i:
num += 1
i //= 10
if num % 2 == 0:
sum += 1
return sum
4.循环中断 break
在 Python 中,break语句是一种控制流工具,它用于终止当前的循环
break是结束循环,它的作用是让当前的while或者for循环停止。
同样的,while循环中也可以使用break来跳出循环,一般用法是在边界条件之外再加一个循环终止的条件。
5.循环中断 continue
在 Python 中,continue语句是一种控制流工具它用于跳过当前循环的剩余部分直接进入下一轮循环这使我们可以在满足某些条件时忽略循环的其些步骤
continue是结束本次循环,继续下一次循环,实际上循环还没有停止;就像打游戏,有很多条命,掉了一条还可以继续玩,只是需要从头开始
练习 1470. 重新排列数组
给你一个数组
nums
,数组中有2n
个元素,按[x1,x2,...,xn,y1,y2,...,yn]
的格式排列。请你将数组按
[x1,y1,x2,y2,...,xn,yn]
格式重新排列,返回重排后的数组。示例 1:
输入:nums = [2,5,1,3,4,7], n = 3 输出:[2,3,5,4,1,7] 解释:由于 x1=2, x2=5, x3=1, y1=3, y2=4, y3=7 ,所以答案为 [2,3,5,4,1,7]示例 2:
输入:nums = [1,2,3,4,4,3,2,1], n = 4 输出:[1,4,2,3,3,2,4,1]示例 3:
输入:nums = [1,1,2,2], n = 2 输出:[1,2,1,2]提示:
1 <= n <= 500
nums.length == 2n
1 <= nums[i] <= 10^3
class Solution:
def shuffle(self, nums: List[int], n: int) -> List[int]:
list = []
for i in range(n):
list.append(nums[i])
list.append(nums[n+i])
return list
练习 1920. 基于排列构建数组
给你一个 从 0 开始的排列
nums
(下标也从 0 开始)。请你构建一个 同样长度 的数组ans
,其中,对于每个i
(0 <= i < nums.length
),都满足ans[i] = nums[nums[i]]
。返回构建好的数组ans
。从 0 开始的排列
nums
是一个由0
到nums.length - 1
(0
和nums.length - 1
也包含在内)的不同整数组成的数组。示例 1:
输入:nums = [0,2,1,5,3,4] 输出:[0,1,2,4,5,3] 解释:数组 ans 构建如下: ans = [nums[nums[0]], nums[nums[1]], nums[nums[2]], nums[nums[3]], nums[nums[4]], nums[nums[5]]] = [nums[0], nums[2], nums[1], nums[5], nums[3], nums[4]] = [0,1,2,4,5,3]示例 2:
输入:nums = [5,0,1,2,3,4] 输出:[4,5,0,1,2,3] 解释:数组 ans 构建如下: ans = [nums[nums[0]], nums[nums[1]], nums[nums[2]], nums[nums[3]], nums[nums[4]], nums[nums[5]]] = [nums[5], nums[0], nums[1], nums[2], nums[3], nums[4]] = [4,5,0,1,2,3]提示:
1 <= nums.length <= 1000
0 <= nums[i] < nums.length
nums
中的元素 互不相同
class Solution:
def buildArray(self, nums: List[int]) -> List[int]:
n = len(nums)
ans = []
for i in range(n):
ans.append(nums[nums[i]])
return ans
练习 2824. 统计和小于目标的下标对数目
给你一个下标从 0 开始长度为
n
的整数数组nums
和一个整数target
,请你返回满足0 <= i < j < n
且nums[i] + nums[j] < target
的下标对(i, j)
的数目。示例 1:
输入:nums = [-1,1,2,3,1], target = 2 输出:3 解释:总共有 3 个下标对满足题目描述: - (0, 1) ,0 < 1 且 nums[0] + nums[1] = 0 < target - (0, 2) ,0 < 2 且 nums[0] + nums[2] = 1 < target - (0, 4) ,0 < 4 且 nums[0] + nums[4] = 0 < target 注意 (0, 3) 不计入答案因为 nums[0] + nums[3] 不是严格小于 target 。示例 2:
输入:nums = [-6,2,5,-2,-7,-1,3], target = -2 输出:10 解释:总共有 10 个下标对满足题目描述: - (0, 1) ,0 < 1 且 nums[0] + nums[1] = -4 < target - (0, 3) ,0 < 3 且 nums[0] + nums[3] = -8 < target - (0, 4) ,0 < 4 且 nums[0] + nums[4] = -13 < target - (0, 5) ,0 < 5 且 nums[0] + nums[5] = -7 < target - (0, 6) ,0 < 6 且 nums[0] + nums[6] = -3 < target - (1, 4) ,1 < 4 且 nums[1] + nums[4] = -5 < target - (3, 4) ,3 < 4 且 nums[3] + nums[4] = -9 < target - (3, 5) ,3 < 5 且 nums[3] + nums[5] = -3 < target - (4, 5) ,4 < 5 且 nums[4] + nums[5] = -8 < target - (4, 6) ,4 < 6 且 nums[4] + nums[6] = -4 < target提示:
1 <= nums.length == n <= 50
-50 <= nums[i], target <= 50
class Solution:
def countPairs(self, nums: List[int], target: int) -> int:
n = len(nums)
sum = 0
for i in range(n):
for j in range(i+1, n):
if nums[i] + nums[j] < target:
sum += 1
return sum
练习 1365. 有多少小于当前数字的数字
给你一个数组
nums
,对于其中每个元素nums[i]
,请你统计数组中比它小的所有数字的数目。换而言之,对于每个
nums[i]
你必须计算出有效的j
的数量,其中j
满足j != i
且nums[j] < nums[i]
。以数组形式返回答案。
示例 1:
输入:nums = [8,1,2,2,3] 输出:[4,0,1,1,3] 解释: 对于 nums[0]=8 存在四个比它小的数字:(1,2,2 和 3)。 对于 nums[1]=1 不存在比它小的数字。 对于 nums[2]=2 存在一个比它小的数字:(1)。 对于 nums[3]=2 存在一个比它小的数字:(1)。 对于 nums[4]=3 存在三个比它小的数字:(1,2 和 2)。示例 2:
输入:nums = [6,5,4,8] 输出:[2,1,0,3]示例 3:
输入:nums = [7,7,7,7] 输出:[0,0,0,0]提示:
2 <= nums.length <= 500
0 <= nums[i] <= 100
class Solution:
def smallerNumbersThanCurrent(self, nums: List[int]) -> List[int]:
n = len(nums)
ans = []
for i in range(n):
num = 0
for j in range(n):
if i != j and nums[j] < nums[i]:
num += 1
ans.append(num)
return ans
练习 2176. 统计数组中相等且可以被整除的数对
给你一个下标从 0 开始长度为
n
的整数数组nums
和一个整数k
,请你返回满足0 <= i < j < n
,nums[i] == nums[j]
且(i * j)
能被k
整除的数对(i, j)
的 数目 。示例 1:
输入:nums = [3,1,2,2,2,1,3], k = 2 输出:4 解释: 总共有 4 对数符合所有要求: - nums[0] == nums[6] 且 0 * 6 == 0 ,能被 2 整除。 - nums[2] == nums[3] 且 2 * 3 == 6 ,能被 2 整除。 - nums[2] == nums[4] 且 2 * 4 == 8 ,能被 2 整除。 - nums[3] == nums[4] 且 3 * 4 == 12 ,能被 2 整除。示例 2:
输入:nums = [1,2,3,4], k = 1 输出:0 解释:由于数组中没有重复数值,所以没有数对 (i,j) 符合所有要求。提示:
1 <= nums.length <= 100
1 <= nums[i], k <= 100
class Solution:
def countPairs(self, nums: List[int], k: int) -> int:
n = len(nums)
sum = 0
for i in range(n):
for j in range(i+1, n):
if nums[i] == nums[j] and i * j % k == 0:
sum += 1
return sum
十、元组
1.元组的定义
在 Python 中,元组是不可变的有序元素序列,这意味着创建后,不能更改、添加或删除元组中元素
列表就像是一个收纳盒,可以有序地存放不同类型的数据
Python中类似的收纳盒不止一种,不同类型的收纳盒我们统称为数据结构
数据结构是用来存储、组织数据,并能对数据进行一定便捷操作的工具。
Python已经为我们准备了列表(list),元组(tuple),字典(dict)等好用的数据结构。
如果说列表像收纳盒,可以有序地在盒子中装上不同的东西。那么元组就像是上了永久密码锁的收纳盒,同样可以有序的装东西,可是里面的东西不可被改变
元组的创建方法
元组使用圆括号 (),而列表使用方括号 []
列表转元组:tuple(list_data)
字符串转元组:tuple("123")
元组和列表一样,可以存储不同类型的数据,元组中的元素,可以是数字,字符串、字符串和数字混合
元素不可修改主要是为了数据安全,例如防止写代码的人因为自己的错误,误修改了里面的数据,或者是一些隐私数据被篡改。
2.元组的基础特性
Ⅰ、不可变性:元组一旦创建,元素不可修改(增删改操作均会引发异常)。这种特性使其适合存储需要保护的数据
Ⅱ、有序性:元组中的元素按插入顺序存储,支持索引和切片访问
Ⅲ、可哈希性:因为不可变,元组可作为字典的键或集合的元素,而列表不行
3.元组的运算
元组内的元素虽然不可以更改,但元组之间可以使用+、+=、*号进行运算,运算后会生成一个新的元组。接下来我们以 + 为例了解元组之间的运算。
使用"+"号连接两个元组,就变成了一个新的元组,它包含了两个元组中的所有元素。
将多个元组合并为一个元组,较多应用于数据分析中
例如,我们可能会从多个文件或数据库中读取数据,然后将它们合并成一个元组,以便进行后续的
处理。
tuple_1 = (1, 2, 3)
tuple_2 = (4, 5, 6)
tuple_3 + tuple_1 + tuple_2
# tuple_3 = (1, 2, 3, 4, 5, 6)
列表支持的功能,元组都支持,除了改变元素
元组的解包
将元组元素分配给多个变量,支持星号表达式处理不匹配的元素个数
a, b, *rest = (1, 2, 3, 4, 5) # a=1, b=2, rest=[3,4,5]
成员检查
使用 in 关键字判断元素是否存在
if 3 in my_tuple:
print("存在")
4.元组的删除
元组中的元素值是不允许删除的,但我们可以使用 del语句 来删除整个元组。
tuple_1 = (1, 2, 3, 4)
del tuple_1
当元组被删除后,输出变量时会有异常信息,输出如下所示,表明元组已被删除
del 关键字不仅能删除元组,也能删除整个列表,以及列表中的元素
十一、字典
1.字典的定义
在 Python 中,字典是一种无序的可变数据类型,它存储键值对,字典的"键"是唯一的,而"值"可以是任何数据类型
在Python中,将两种数据关联在一起形成一个元素,由多个这样的元素组成的数据类型称为字典,又称为dictionary
字典中的键可以由任意不可修改的数据类型组成(数字,字符串,元组),组成字典元素的两个数据一一对应,分别是键(key) 和 值(value)
在一个字典中不会有相同的两个键,而每一个键也只能对应一个值
字典(dictionary)是一种数据类型,按照键值对的方式存储数据。键是索引 key,值是数据 value,键和值之间的分隔符为 :,键值对之间使用 , 分隔。
字典的创建方法
Ⅰ、直接定义:使用花括号{},键值对用冒号:分隔
empty_dict = {} # 空字典
person = {"name": "Bob", "age": 30} # 带初始键值对
Ⅱ、构造函数:通过dict()函数创建,支持键值对序列或关键字参数
dict_from_list = dict([("a", 1), ("b", 2)]) # 从列表创建
dict_from_kwargs = dict(name="Charlie", age=22) # 从关键字参数创建
Ⅲ、字典推导式:快速生成字典,支持过滤和转换
squares = {x: x**2 for x in range(5)} # {0:0, 1:1, 2:4, 3:9, 4:16}
字典使用花括号{},元组使用圆括号 (),而列表使用方括号 []
2.查找字典元素
字典和列表一样,也会有查找、删除、添加、修改等功能,但因为字典是没有顺序的结构,在功能的使用上,有所不同。
字典是没有顺序的,也就没有索引,所以只能通过字典的键(key) 来查找对应的值(value)
我们同样通过索引的方式查找键对应的值,索引用方括号[],在其中填入键。
键相当于列表中的下标
通过键(key) 的索引查找列表元素值(value)
使用 get(key, default) 安全访问
3.增加字典元素
字典作为一种可变的数据类型,也可以进行添加与修改,但添加与修改的方式与列表不同。
字典是可以改变的,就像图书馆的书籍也是可以增补的。但是字典中的元素也是要以键值对一一对应的形式添加或删除
字典的键是不能重复的,当我们尝试添加一个已经存在的键时,就会将该元素覆盖。所以对字典的修改,就是对字典的某个已经存在的键重新赋值,修改字典,其实是对字典中已经存在的键重新赋值
4.删除字典元素
使用 del语句 会删除整个元组,在字典中,del语句 用来删除指定的键值对。
dict.pop(key):删除并返回值
dict.popitem():删除并返回最后一个键值对
dict.clear():清空字典
5.常用方法
① .keys():返回所有键的视图
② .values():返回所有值的视图
③ .items():返回所有键值对的视图
④ .update(dict2):合并字典
⑤ .setdefault(key,default):安全获取值,若不存在则设置默认值
练习 2351. 第一个出现两次的字母
给你一个由小写英文字母组成的字符串
s
,请你找出并返回第一个出现 两次 的字母。注意:
- 如果
a
的 第二次 出现比b
的 第二次 出现在字符串中的位置更靠前,则认为字母a
在字母b
之前出现两次。s
包含至少一个出现两次的字母。示例 1:
输入:s = "abccbaacz" 输出:"c" 解释: 字母 'a' 在下标 0 、5 和 6 处出现。 字母 'b' 在下标 1 和 4 处出现。 字母 'c' 在下标 2 、3 和 7 处出现。 字母 'z' 在下标 8 处出现。 字母 'c' 是第一个出现两次的字母,因为在所有字母中,'c' 第二次出现的下标是最小的。示例 2:
输入:s = "abcdd" 输出:"d" 解释: 只有字母 'd' 出现两次,所以返回 'd' 。提示:
2 <= s.length <= 100
s
由小写英文字母组成s
包含至少一个重复字母
class Solution:
def repeatedCharacter(self, s: str) -> str:
dict = {}
for i in s:
if dict.get(i):
return i
dict[i] = 1
练习 1512. 好数对的数目
给你一个整数数组
nums
。如果一组数字
(i,j)
满足nums[i]
==nums[j]
且i
<j
,就可以认为这是一组 好数对 。返回好数对的数目。
示例 1:
输入:nums = [1,2,3,1,1,3] 输出:4 解释:有 4 组好数对,分别是 (0,3), (0,4), (3,4), (2,5) ,下标从 0 开始示例 2:
输入:nums = [1,1,1,1] 输出:6 解释:数组中的每组数字都是好数对示例 3:
输入:nums = [1,2,3] 输出:0提示:
1 <= nums.length <= 100
1 <= nums[i] <= 100
解法 ①
class Solution:
def numIdenticalPairs(self, nums: List[int]) -> int:
n = len(nums)
num = 0
for i in range(n):
for j in range(i + 1, n):
if nums[i] == nums[j]:
num += 1
return num
解法 ②
dict.get():是字典操作的核心功能之一,用于安全获取键对应的值
dict.get(key, default=None)
key:要查找的键
default:(可选) ,若键不存在,返回该默认值(默认为None)
class Solution:
def numIdenticalPairs(self, nums: List[int]) -> int:
dict = {}
n = len(nums)
num = 0
for i in range(n):
num += dict.get(nums[i], 0)
dict[ nums[i] ] = dict.get(nums[i], 0) + 1
return num
6.字典的高级应用场景
Ⅰ、统计词频:通过遍历字符串并累加字典值
text = "apple banana apple"
word_count = {}
for word in text.split():
word_count[word] = word_count.get(word, 0) + 1
Ⅱ、快速查找表
city_codes = {"Beijing": 10, "Shanghai": 21}
print(city_codes["Shanghai"]) # 输出:21
Ⅲ、嵌套结构:字典可嵌套其他字典或列表,表示复杂数据关系
employee = {
"name": "Alice",
"address": {"city": "New York", "zip": "10001"},
"skills": ["Python", "SQL"]
}
print(employee["address"]["city"]) # 输出:New York
Ⅳ、函数返回多值:通过字典打包返回多个值,提升代码可读性。
def get_user_info():
return {"name": "Bob", "age": 25, "city": "Los Angeles"}
info = get_user_info()
print(info["name"]) # 输出:Bob
7.数据结构小结
列表,元组,字典三种数据结构的共同特点是:
1.可以存储多个元素
2.存储的元素可以是不同的类型
列表是有序的可变的数据结构
有序:可以通过索引来访问列表中的元素
可变:可以通过赋值、删除、插入等操作来修改列表中的元素。
元组是一种有序的不可变的数据结构
有序:可以通过索引来访问元组中的元素。
不可变:元组中的元素不能被修改 ,但元素与元素之间可以进行运算或者整体删除。
字典是一种无序的可变的数据结构
无序:使用键值对的方式来存储元素,通过键来访问字典中的元素。
可变:字典可以通过赋值、删除、插入等操作来修改字典中的元素。
定义元组、列表个字典的方式如图所示,分别使用英文小括号(),方括号[]、花括号{},三种数据结构的每一项元素都是由逗号分隔开
元组和列表使用索引来访问某一个位置的元素,字典通过键来查找对应的值
我们可以使用切片的方式来截取元组和列表中多个连续的元素。
切片需要使用冒号来分隔切片开始的位置和终止的位置。
同时,遵循“取左不取右的原则,取左边的数据,不取右边的数据
切片时,开始位置和结束位置的数字,还有三种情况:
① 只填写结束位置的数字;默认从第一个元素开始切片
② 只填写开始位置的数字;默认从开始位置切片,取到最后一个元素
③ 两侧数字都不填写; 取列表中的所有元素
修改列表:可以用列表的索引访问需要修改的元素并重新赋值
修改字典:使用字典的键访问需要修改的元素并重新赋值
修改元组:元组不能被修改
在列表中插入元素,使用insert()语句可以在列表的任意位置添加元素
元组的计算:元组中的元素虽然不能改变,但元组之间可以进行数学运算形成新的元组。
使用"+"号连接两个元组,就变成了一个新的元组,它包含了两个元组中的所有元素。
在字典中添加元素:在字典中添加新元素的方法是指定一个新的键,并对它进行赋值
删除字典元素
使用del方法,通过元素的键来删除,会删掉整个键值对,也可能是删除整个字典
删除整个元组
使用del方法,不能删除元组中的个别元素,但可以删除整个元组
删除整个列表
使用del方法,同样能删除整个列表,也可以删除列表中的元素
使用pop方法,也可以删除列表中的元素
列表、元组、字典的常见报错
我们在索引和查找指定元素时,最常出现的错误提示是“索引错误”,indexError如图所示元组-共有5个元素,索引的范围是0-4。不存在索引为5,会出现"out of range"的报错
那要如何快速找到元组的元素个数,避免出现索引超过的错误呢?此时可以使用len()函数
len()方法象一个尺子,可以获取测量对象的长度
len()方法可以通过直接索引数据结构来获得其长度,也就是元素个数
十二、函数使用
1.函数的定义
在编程中,函数是一段用于执行特定任务的可重用代码块,可以通过定义函数名和参数列表来创建函数
print() 我们已经很熟悉了,它还有个专业的名词叫做函数(function),每个函数都有自己特定的功能,比如print()的功能就是在电脑屏幕上打印输出一些数据。
函数具有三个特点,第一个是特定功能,比如有些函数的功能是打印输出一些数据,有些函数的功能是完成特定的计算;第二个是输入,使用函数的时候可以输入一些数据;第三个是输出,使用函数以后,它会输出一些数据;
函数的定义是指函数的具体代码实现,我们需要这几个部分:1.def 关键字(define),就是用来定义函数的关键字;2.函数名 add_3,它标识了函数;3.函数参数部分(num):,4.最后是函数返回值的关键字 return
2.函数的调用
函数的命名和变量一样,我们只使用字母,数字和下划线,同时不用数字开头。建议的命名风格是:函数名一律使用小写字母,字母(及数字)之间使用下划线连接,同时尽量做到看函数名去表达函数的功能(见名知意)
完成了函数的定义以后,我们就可以开始使用这个函数了,使用函数的过程有个专业名词:函数调用。需要注意的是,函数一定需要先定义,再调用,毕竟我们需要先有函数的代码,才能执行它。
需要注意的是,函数定义的时候,是有冒号 : 的,以及下面的归属于这个函数的代码块是需要缩进的。而在函数调用的时候,我们则不需要这些。
练习.1732. 找到最高海拔
有一个自行车手打算进行一场公路骑行,这条路线总共由
n + 1
个不同海拔的点组成。自行车手从海拔为0
的点0
开始骑行。给你一个长度为
n
的整数数组gain
,其中gain[i]
是点i
和点i + 1
的 净海拔高度差(0 <= i < n
)。请你返回 最高点的海拔 。示例 1:
输入:gain = [-5,1,5,0,-7] 输出:1 解释:海拔高度依次为 [0,-5,-4,1,1,-6] 。最高海拔为 1 。示例 2:
输入:gain = [-4,-3,-2,-1,4,3,2] 输出:0 解释:海拔高度依次为 [0,-4,-7,-9,-10,-6,-3,-1] 。最高海拔为 0 。提示:
n == gain.length
1 <= n <= 100
-100 <= gain[i] <= 100
class Solution:
def largestAltitude(self, gain: List[int]) -> int:
high = 0
last = 0
for i in gain:
last += i
high = max(high, last)
return high
3.函数名
函数名又叫函数的命名,我们知道,要定义一个函数,就需要用到关键字def,它是英文define(定义)的简写,def后面我们就可以定义这个函数的函数名了
函数名命名和变量名命名一样,只能使用下划线、字母和数字,且数字不能作为开头
从代码风格的角度来说,我们对函数名的命名有两个原则:第一个是最好从函数名本身就能看出函数的功能;第二个是函数名一律小写,如果有多个单词我们可以用下划线隔开
4.函数参数
函数需要一些输入,我们称它为函数参数
函数参数是我们在调用函数的时候,输入给函数的数据。之前我们只使用过一个参数,现在我们来了解一下更进阶的函数参数用法
函数参数是用来从“函数外部”向“函数内部”传递数据的,就是我们在代码中调用函数的时候通过函数参数向函数传入数据。
值得注意的是,函数定义中的参数数量,需要和函数调用时的参数数量,保持一致,否则程序会报
错
5.函数返回值
函数需要一些输出,我们称它为函数返回值
那么函数内部如何向函数外部输出数据呢?我们通过函数返回值来实现这一数据传递
函数返回值通过关键字return实现,空格后面的数据,就是具体返回给函数外部的数据
一个函数定义如果不显性声明返回值的话,这时候会返回一个空值None
6.函数必选参数
函数参数分为3种:① 必选参数;② 可选参数 ③ 不定长参数,分别对应不同的应用场景。
必选参数就是指在调用这个函数的时候,必须使用的参数,不输入这个参数就无法正确调用函数
7.函数默认参数
第二种函数参数是默认参数,意思是它有一个默认值,在调用函数的时候,如果我们不输入这个参数,它就使用默认值,所以叫默认参数
8.函数不定长参数
当我们需要更灵活地传入参数时(比如:有时候传入2个参数,有时候传入5个参数这种参数个数不确定的场景),我们就可以使用不定长参数
不定长参数又叫可变参数,“可变”具体是指参数的数量是灵活可变的,不固定的。
星号*是表明不定长参数的固定语法格式
def sum_up(*num):
sum_number = 0
for counter in num:
sum_number = sum_number + counter
return sum_number
number_1 = sum_up(1, 2, 3, 4)
print(number_1)
number_2 = sum_up(1, 2, 3, 4, 5, 6, 7, 8, 9)
print(number_2)
9.函数执行顺序
入口丢进去的瓶子和水就是输入,出口出来的瓶装水就是输出,“有魔法的加工盒”就是函数。不同的函数有不同的功能,就像有些“加工盒”加工出来的水是矿泉水,有些“加工盒”加工出来的“水”是果汁。
第一种执行顺序是代码默认的,它叫顺序执行或者简称顺序,也就是从上到下顺序地执行每行代码
print("一")
print("二")
print("三")
print("四")
第二种代码执行顺序是判断,会根据判断的不同条件执行不同的代码分支
第三种执行顺序是循环,它根据循环条件,决定执行几次代码
第四种顺序是代码的“跳转执行”,简称跳转,函数以及后面将要学习的类和对象,都涉及到类似这样的执行顺序
def add_three(num):
new_number = num + 3
return new_number
number1 = 10
number2 = add_three(number1)
print(number2)
10.Python中的一些内置函数
函数主要分为两大部分:
第一部分是函数定义,它确定了函数功能和使用方法;
第二部分是函数调用,它完成了代码中对函数的使用。
函数定义中,包含了三大主要部分:
① 函数名;② 函数参数;③ 函数返回值。
其中函数名和函数参数涉及到的关键字是def,函数返回值涉及的关键字是return
例如,print()、range()、len()等函数都是Python定义好的函数,我们只需要使用它就可以了
min():首先是从一系列数字里面挑选出最小值(minimum)的内置函数
max():从一系列数字里面挑选出最大值(maximum)的内置函数
十三、类
1.类的定义
Python中,类是一种用户定义的复杂数据类型,类提供了一种组织代码和数据的方式,用于创建现实世界的蓝图
下面的代码就是一个代表老师“类别”的代码,其中类的命名就来自于对class单词的翻译(一类种类的意思)。
class Teacher:
def __init__(self):
self.name = "Susan"
self.subject = "English"
self.age = 33
self.height = 164
self.weight = 105
我们可以看到,一个类的定义包括了:① 关键字class ② 类名 ③ 语法固定符号冒号(:) ④ 一个初始化函数_init_(self)
注意:init左右各有两个下划线,需要传入self这个特殊的参数。
定义类中的函数时,要带上”self“这个参数
每个类都有一个初始化函数 __init__(self),它的功能是给一些“属于”类的变量赋值。它叫初始化是因为,这个函数是跟随类代码初始化的时候就会调用的。
这个函数的init单词左右各有2个下划线,不要漏掉;类中函数定义时要带上self变量,也不要漏掉
2.类的属性
同样的,一个类也有两大部分构成,其中一个是类的属性,类似于老师的名字、学科、年龄等等,在代码中它是以变量的形式出现。
属性(property)又叫成员变量,它是归属于类的一个变量,用来描述类的一些特性。
比如老师有名字(self.name),有学科(self.subject),有年龄(self.age)。这里的名字、学科、年龄,都是老师(Teacher)这个类的属性。
为什么这个变量看起来有些奇怪,前面还有个前缀self.?这其实是用来表明这个属性“归属于”这个类自己的(self)。比如 self.name,就代表着:“自己的名字”,self等于“自己”,句号.等于“的”,name等于“名字”。
3.类的方法
方法又叫成员函数,它是“归属于”类的一个函数,用来实现类的一些功能。
十四、类和对象
1.对象
类是指一个抽象的类别(比如”老师”),是指代一个人群的所有人。
而生活中我们往往遇见的是一个个具体的人,比如你初中的语文老师阿飞,高中的政治老师阿番他们是一个具体的对象。
所以类和对象的关系是 —— 类是对象的模版,对象是类的实例。
即使只有初始化函数,当一个对象被创建以后,它也有了自己的数据
2.实例化
类的命名是字母直接连在一起,单词的首字母大写。对象的命名是遵从变量的命名规则,使用小写字母,单词之间用下划线连接。
实例化就是以某个类为模板,创建对象的过程
class MobliePhone:
def __init__(self, brand, the_type):
self.brand = brand
self.the_type =the_type
def print_brand_type(self):
print(self.the_type)
def print_brand(self):
print(self_brand)
mobile_phone_a = MobilePhone("IPhone", "18")
mobile_phone_b = MobilePhone("xiaomi", 12)
实例化的具体代码执行时机,是在创建对象的时候。这时候默认调用了初始化函数__init__()。我们不用显性或者编写代码来调用这个函数,是因为这个调用过程默认是静默的。
3.面向对象编程
按照过程一步一步执行的做法,在编程中叫做面向过程编程(Procedure Oriented Programming)
面向对象编程的核心在于以对象为编程单位。
它把相关的数据(对象的属性)和相关功能(对象的方法)集合在一起,放在类和对象这个机制里面。
这样我们编程中就可以以对象为单位,而不用以一行一行的代码为单位来展开了
相较于面向过程编程,面向对象编程有两大优势:
① 减少代码数量;
② 降低代码复杂度。
python内置了很多类和对象,比如之前我们学过的 list 和 dict,他们都是一个类,我们可以用他们来创建一些可以使用的对象。
列表 list 的常见方法
列表中的 count() 方法的功能是统计某个元素在 list 中出现的次数
列表中的 index() 方法的功能是寻找某个数在列表中的位置(第一次出现)
列表中的 remove() 方法的功能是删除某个数(第一次出现)
列表中的 reverse() 方法的功能是逆转排序整个列表
字典 dict 的常见方法
字典中的 keys() 方法的功能是返回字典的所有键(key)
字典中的 values() 方法的功能是返回字典的所有值(value)
字典中的 clear() 方法的功能是请空字典所有的键和值
十五、类和函数共性
1.封装
类和函数有很多相似之处,除了都需要有关键字来定义。还有三个共性:① 封装 ② 变量作用域
③ 跳转执行
封装的核心思想是,“不用告诉我你怎么做的,给我结果就好”,就像我们只需要知道水和瓶子会产出瓶装水。
同样在代码中,我们在调用一个函数或者使用一个对象时候,也不需要知道你“怎么实现这个功能的",只需要知道我应该输入什么,你会给我什么输出结果
封装的具体特征是:隐藏内部的变量和过程代码,仅对外暴露公开的接口。而这个公开的接口包括:函数名,类的方法名,需要输入的参数,会返回的数据
一个类对外暴露的公开接口包括:类名,初始化函数的参数,类的方法等
公开的接口也可以分为输入和输出两部分,比如函数名/类名,参数个数,参数类型就属于
输入的部分;
而函数返回值和类的方法的返回值,就属于公开接口的输出部分,比如直接调用列表list的count()方法会帮助我们计算某个数值出现的次数。
封装的核心思想是:隐藏封装内部的变量和过程代码,仅对外暴露公开的接口
2.变量作用域
变量作用域的意思是指:一个变量在程序中的哪个区域的代码能够被正常使用
一个在函数内部的变量,是无法在函数外部访问的。这个函数内部变量的作用域就只在函数内部。
一个在函数外部的已有的变量,不会受到函数内部过程的影响。
同样对于类的属性(成员变量),在类的内部访问方式和在外部访问方式也不一样。
在内部任何一个地方(比如任何一个内部方法)要访问这个属性的时候,直接用 self. 就可以访问了
外部要访问这个属性,必须使用对象名加上 . 才能访问,比如:mobile_phone_a.brand
函数和类私有的变量,都需要在它们内部的代码来访问。
对于函数,外部无法访问函数内部的变量。
对于类,需要通过对象来访问其内部的属性。
3.跳转
在函数中的跳转:
① 在调用函数的时候,代码执行跳转进入函数内部;
② 函数执行完毕以后,跳转到调用函数的地方。类和对象的跳转也类似