二、Python
8. Python入门仪式
写Python程序方式1 可以自定义python文件, 文件的后缀名是.py 在控制台上可以通过python解释器 向计算机解释python程序 写Python程序方式2 在控制台上 借助指令python进入到python环境中 在环境中书写程序 写Python程序方式3 借助编辑器[Python提供的编辑器idle 或者 使用Pycharm]
向Python世界say Hello 简单而言 借助python程序输出hello world print 输出的时候 不同的数据 书写格式是不一样的 对应的数据类型是不一样的 具有相同特征的鬼节为一个类型的数据 简单的数据类型 整型数据int --- 数据全部都是整数 浮点型数据float --- 数据全部都是小数 布尔类型数据bool --- True/False 字符串类型数据str --- 如果数据是单个或者多个字符拼在一起的 就是字符串类型 标识是引号 不区分单双引号 注意:要输出多个字符或者单个字符 需要使用引号包含 而不能直接使用符号 "hello world" 正确的 hello world 错误的
print的使用 help帮助功能 可以查看使用的功能的方式 print(values, sep=' ', end='\n', file=sys.stdout, flush=False) values: 表示输出的数据 - 可以输出多个数据 每个数据之间使用逗号分开即可 [注意写程序所有点符号都是在英文状态下的] >>> print(10) 10 >>> print(10, 3.14) 10 3.14 >>> print(10,3.14,True,"hello world") 10 3.14 True hello world >>> sep 默认值是空格符号 设置的是当输出多个数据时 每个数据之间的分隔符 可以进行自定义 >>> print("h","e","l","l","o") h e l l o >>> print("h","e","l","l","o",sep="") hello >>> end \表示的是转义符 用于转义\后面的符号 \n --- 把n换成了换行的意思 默认值是换行 作用: 执行多条输出语句时[写了多个print] 每个print输出的内容是以换行结尾的 如果一行有多个语句[单独的一个功能], 语句之间使用分号隔开 file ----> 表示的是 默认将内容输出到控制台 更改:将输出的内容存于到指定文件里 前提需要打开一个文件 打开模式设置写入w的状态 打开模式: r --- 读取文件 read w --- 写入文件 write > a --- 写入文件 append >> flush----> 输出的内容是否及时刷新
9. 编程语言的描述
程序员需要与计算机进行交互, 进而完成对应的功能
能完成交互前提是 程序员需要使用计算机识别的语言来沟通
计算机中的数据是二进制格式的
人们制定了一种规范去和计算机进行交互, 这个规则对应的语法就是编程语言
学习编程语言 其实学习的就是语法规则
语法: 制定好的固定格式 使用这个语法直接嵌套就可以了
10. Python发展史
Python底层是通过C语言来完成 1991年正式发布的 研发者是一个荷兰人 “硅叔” 1989年
1999年 支持了网站开发 爬虫开发
2000年出现了python2.0版本
2004年出现了python2.4版本 — Django出现了
2008年出现了Python2.6
2.x中的输出的格式:
print "hello world"
3.x中的输出格式:
print("hello world")
2008年底的时候出现了python3.0 — 与2.x的版本完全不兼容
2010年的时候出现了2.7的版本 — 向3.0的过度
2020年不再对2.x的版本进行维护 学习的是3.x的版本
现在不要使用3.7 第二阶段Django 使用的版本1.x的版本 长久版 不兼容3.7
11. 注释
用自己的语言 来描述代码的功能使用 便于自己后期的理解
因为现在接触的代码全部都是英文的
注释的格式:
单行注释 — 只能注释掉一行内容
格式:
#注释内容
多行注释 — 三对引号[引号不区分单双]
格式:
''' 注释内容 '''
建议对自己的代码多加注释
12. 变量
变量的概念:
某个内容的值是变化的
小学知识 一元一次方程
题目:
车a在马路上以80km/h的形式速度匀速形式 问多少小时后 行驶1000km??
解: 设x小时后行驶1000km
80 * x = 1000
x = 1000/80 = 12.5
设置的x就是一个变量 根据不同的题意 x对应的内容是不同的
变量对应的数据是变化 如果想获取这个数据 不能准确的获取 但是可以通过x获得对应的值
车b在马路上行驶 100km/h a行驶1000km后 b开始出发 问b多长时间追上a
设y小时后 b追上a
80 * x + 80 * y = 100 * y
80 * 12.5 + 80 * y = 100 * y
20 * y = 1000
y = 50
变量的作用:
存储运算过程中一些变化的数据的结果的,便于后面的其他情况的使用
在程序中对变量的解释:
内存:
把他比作成高楼大厦, 分布着很多小的房间[比作成字节],数据占用的是字节,如果有多个字节,可以理解成将这个多个小房间打通称为一个地址,高楼大厦中每个房间都有字节标号[地址]
在内存中查找某个数据, 该数据对应的地址查找比较方便快捷的
比如:外卖人员给你送外卖, 北京市当做内存 外卖人员通过地址定位到送货位置的
变量的解释:
变量是来存放数据的,数据是在内存中开辟对应的字节数来存放的,这个数据就有一个对应的地址,把这个地址给设置给对应的接收者, 通过接收者接受到地址获取其对应的数据,这个接受者会有一个名字, 这个名字称之为变量名
这个变量名是程序员自己定义的, 程序中程序员自己定义的名字需要遵守一些规范, 这个规范称之为标识符
规范:
标识符的组成: 数字 字母 下划线 组合的时候注意事项: 1. 自定义的名字不能以数字开头 2. 自定义的名字不能使用Python中占用的名字[关键字] 和 备用的名字 ----> 只要python使用了 咱们就不能再使用 如果使用会将python中提供的原有意义给覆盖掉, 如果再想使用原有意义就使用不了了 3.尽量做到见名思意
现在接触到的自定义名字有哪些?? 1.自定义python文件名 规范:英文字母全部是小写的, 每个单词之间使用下划线隔开 first_demo 2.自定义变量名 规范:英文字母全部是小写的, 每个单词之间使用下划线隔开 max_value 3.自定义项目的名字 规范: 单词的每一个英文字母大写 遵守的是大驼峰 FirstProject
在Python中声明变量的时候的注意事项: 1. 在使用该变量之前必须先进行声明 并赋予初始值 [定义出来] 2. 变量声明的格式: a.声明一个变量: x = 10 或者 x:数据类型 x = 10 例如: 7变量的声明 #1. 声明立即进行初始化 x = 10 print("x") print(x) ''' 在使用一个符号的时候 加引号和不加引号的区别: 加上引号 这个符号表示的是一个字符串类型的数据 不加引号 这个符号表示的是一个变量名 要使用的是他对应的数据 ''' #2. 声明先不赋予初始值 再使用之前赋予 y:int y = 10 print(y) b.声明多个变量 i.多个变量的值是相同的 x = y = z = 10 ii. 多个 变量的值是不同的 x, y, z = 10, 11, 12
13. 数据类型的初见
不同的特征的数据 对应者不同的数据类型
系统提供的数据类型:
针对于数值的数据类型 : 整型 浮点型 复数型[很少用]
布尔类型 : 用于标记状态的 成立或者不成立 只有两个值 True和False
字符串类型 : 容器, 存放的多个字符,使用引号包含单个或者多个字符的
列表类型 : 容器 可以存放多个变量的数据
元组类型 : 容器, 也可以存放多个变量
字典类型 : 容器 存放的是具有映射关系的数据 一对一的 键值对
集合类型 : 容器 具有排重的作用 —> 里面的数据不能重复的
13.1 数值类型
整型 类型名字 int 这种类型的数据 全部都是整数 python2.x int这个类型 数据占用的字节数是4B long 长整型 占用的字节数是8B python3.x中去掉了long 只保留了int int占用的字节数与原本的long一致的 8B 浮点型 float 这种类型的数据全部是小数 复数型[很少使用] complex 复数有实部和虚部之分 数据格式是 实部+虚部j
13.2 布尔类型
bool 什么情况下使用该类型的数据? 用于标记某种状态的时候 这种状态只有两种情况 bool的值只有两个 True / False
13.3 字符串类型
str 是一个字符序列 --- 包含字符的一个容器 使用引号来包含单个或者多个字符 字符串的内容一旦确定是不允许更改的 字符串中每个字符也有自己的编号 可以通过编号获取该位置对应的字符 获取格式: 接受字符串的变量名[索引]
13.4 列表类型[使用比较多]
list 容器, 可以存放多个变量的值, 表示是使用中括号[]来表示的, 也就是在中括号中存放多个数据, 每个数据之间使用逗号隔开. 有序的序列[存放顺序和显示顺序是一致的] 存放在列表中的数据都有自己的编号 这个编号是从0开始的 编号还称之为索引 下标 脚标 可以通过编号来查找数据或者这个这个位置的数据 ------------------------------------------------------------------------------ a.可以添加数据 接受列表的变量名.append(数据) #在最后添加的 b.在指定位置插入 接受列表的变量名.insert(索引位置, 数据) c.移除元素 1.删除指定数据 接受列表的变量名.remove(数据) 删除是第一次出现的数据 2.删除末尾元素 接受列表的变量名.pop() 3.删除指定位置的元素 接受列表的变量名.pop(索引) d.获取容器的长度 len(接受容器的变量名)
#Python是一个动态语言 - 变量的类型是根据赋予的值来决定的 a = 10 #查看变量对应的类型的方式 #1. type(变量名) print(type(a)) #2. isinstance(变量名, 类型名字) 查看该变量是否是指定类型 print(isinstance(a, int)) #True print(isinstance(a, float)) #False a = 10.2 print(type(a)) #字符串类型 a = "hello" print(type(a)) #根据索引获取指定位置的字符 ch = a[0] print(ch) ''' a[0] = "m" TypeError: 'str' object does not support item assignment 字符串内容一旦确定 不允许后期发生修改 ''' #a[0] = "m" #print(a) #列表 l1 = [12, 3.14, True, "hello"] print(l1) value = l1[1] print(value) l1[1] = 3.1415926 print(l1) l1.append(99) print(l1) #获取长度 length = len(l1) print(length) #在指定位置插入 l1.insert(0, "头儿") print(l1) #末尾追加 l1.append(12) print(l1) #删除 l1.remove(12) #删除第一次出现的元素 print(l1) #删除末尾元素 l1.pop() print(l1) #删除指定位置 l1.pop(2) print(l1)
13.5 元组类型
tuple 每设置一个数据 都在内存中有其独立的地址 获取数据对应的地址 id(变量) 容器,用于存放多个变量的数据,长度一旦确定是不允许发生变化的,而且元组中元素的数据地址不允许发生变化 在元组中添加的元素也有对应的编号,可以通过编号获取元素的值 元组声明的时候 使用小括号()来包含元素的 注意: ()具有提高优先级的意义 如果声明元组时 元素只有1个 需要在该元素的后面添加逗号分隔 告诉Python解释器这个小括号是元组数据的代表 而非是提高优先级的意义。如果不加这个逗号的话 解释器会将其解释成提高
**注意:**Python这门语言对于格式对其很讲究 平级的语句不允许出现缩进的情况 左边必须是平齐的
m = 32 print(id(m)) m = 12 print(id(m)) tuple0 = (23, 56, 78, True) print(type(tuple0)) print(tuple0) value = tuple0[0] print(value) ''' : 'tuple' object does not support item assignment ''' #元组中数据的地址不能发生改变 不能被再次赋值 # tuple0[1] = 77 # print(tuple0) # 注释的快捷键 ctrl + / 解开注释 再使用ctrl + / #如果只有一个元素的时候 必须在该元素后添加逗号 才会将该数据解释成元组 #否则 小阔号就是一个提高优先级的含义 会将小括号中的数据赋值给变量名 tuple1 = (10,) print(tuple1) print(type(tuple1))
13.6 集合类型
set 容器 没有索引一说 主要作用用于排重(排除重复) 无序的---添加顺序和最终的顺序可能不一致 但是数据位置一旦确定 不管再怎么运行 位置都不会发生变化 set(容器)------>集合类型
#集合 list1=[77, 28, 31, 52, 44, 28, 77, 66, 28] set0 = set(list1) print(set0) >>>{66, 44, 77, 52, 28, 31}
13.7 字典类型[使用比较多]**
dict 存放的是具有映射关系的键值对 键值对的格式:key:valus 是使用{}来包含多个键值对的,每个键值对之间使用逗号隔开 {key:valus,key1:valus1,key2:valus2} 字典没有索引一说,是通过键查找值得,要求:键不允许重复 而且一般键的地址是不允许发生变化的 键使用的是不可变得数据类型(常用的就是整型,字符串类型) 通过键来查找值得方式: 接受字典的变量名[键名] 这种方式如果键不存在 会报错 会报错keyError 程序会终止 或者 接受字典的变量名.get(键名) 如果键不存在 不会报错 返回一盒个特殊值None 在字典中新增键值对 接受字典的变量名[键名]=值 如果键名已经存在 将新值覆盖旧值 不存在会当做一个新的键值对添加 移除键值对 方式1: 接受字典的变量名.pop(键名) 方式2: del 接受字典的变量名[键名]
#字典 dict0 = {"英语":88, "数学":99} print(dict0) #没有索引一说 #KeyError: 0 键错误 -- 表示的字典中没有0这个键 # item = dict0[0] # print(item) #通过键来查找值的方式 # value = dict0["英语1"] # print(value) value = dict0.get("英语1") print(value) print(len(dict0)) print(dict0) dict0["语文"] = 65 print(dict0) dict0["英语"] = 65 print(dict0) # dict0.pop("数学") # print(dict0) # del dict0["数学"] # print(dict0)
14. 输入功能
输出功能: print(数据) -- 结果显示在控制台上 输入功能: 结果 = input(提示语:提示用户输入什么数据) 结果接受的就是用户输入的数据 注意 python2.x和python3.x的区别 在python2.x的版本中 输入什么格式的数据 结果就是该数据对应的类型 在Python3.x的版本中 不管输入的是什么格式的数据 结果都是字符串类型的
15. 不同的类型之间的转换
1.将数据转化为整型 一般使用会将字符串 / 小数转化为整型 转化的方式 int(数据) 注意:转换字符串 字符串可以以+或者-开头 其余的必须是整数数字格式的 不允许包含其他数字内容 如果包含的话就会转换失败 报错
#类型转换 x = 3.14 print(x) res = int(x) print(res) s = "+99." res = int(s) print(res) print(type(res))
2.转化为浮点型 将数值 / 字符串进行转换 float(数据) 注意: 字符串 可以包含正确的正负符号 可以包含一个小数点. 必须满足的小数/整数的数据格式 否则的话将会转换失败 报错 res = float(3) print(res) res = float("9..9") print(res)
3.转化为bool类型 值只有True / False 数值类型: 非0即为True 字符串类型: 非空字符序列即为True 空字符序列:只有一个引号 引号中没有任何内容"" 其他类型: 非None即为True bool(数据)
4.将数据转化为字符串类型 str(数据)
5.解析字符串 eval(字符串) 可以将字符串中式子提取进行对应的运算 也可以提取字符串中对应的数据 结果类型为字符串中数据的类型 eval的使用 解析字符串 扒掉外层字符串的衣服 剩下的是什么 就是什么 "a" -----> 字符串数据 a -----> 起的变量名 如果使用它的话是使用该变量对应的数据的 eval("a") =====> a #注意 如果前面没有声明过a这个变量 使用的话报错/ code="12+34" res=eval(code)#拔掉字符串这层衣服 print(res)#输出为int型46 con="10" res=eval(con) print(res)#输出 int型10 con1="[12,34,56]" res=eval(con1) print(res)#输出list型[12,34,56] con2="(12,34,56)" res=eval(con2) print(res)#输出tuple型(12,34,56)
6. 编码 将生活中常用的数据与计算机数据关联 关联的中间介质是十进制数据 生活中的数据 <-----> 十进制 <------>二进制 获取生活中某个字符对应的十进制数据 ord(单个符号) "a" ====> 97 "A" ====> 65 "0" =====> 48 你 ====> 根据十进制数据获取其对应生活中的字符 chr(十进制数据) #要求十进制数据的范围: 0-0x110000 ====> 十进制范围 [0, 1114112)
7.进制之间的转换 将数据转化为16进制 hex(数据) 转化为二进制 bin(数据) 转化为八进制 oct(数据)
16. 运算符
16.1 算术运算符
基本算术运算符: + 在数值类型中将两个数进行求和 在字符串类型中 将两个字符串进行拼接 生成一个新的字符串 ------------------------------------------------------------------------------- - 数值中 求差 ------------------------------------------------------------------------------- * 在数值类型中 求积 在字符串类型中 将字符串原有内容重复n遍 生成一个新的字符串 ------------------------------------------------------------------------------- / 数值中做商 保留小数 ------------------------------------------------------------------------------- // 数值中做商 结果只保留整数 ------------------------------------------------------------------------------- % 取模 做商之后取的是余数 一个数a能被另一个数b整除 === 做商之后没有多余的数剩下 a % b == 0 ------------------------------------------------------------------------------- ** 幂数 x ** y ===> x的y次方 ------------------------------------------------------------------------------- 复合赋值运算符 = += a += b =====> a = a + b -= a-=b ====> a = a - b *= a *= b ====> a = a * b /= a /= b ====> a = a / b //= a //= b ====> a = a // b %= a %= b ====> a = a % b **= a **= b ====> a = a **b
a = 10 b = 20 ''' 等号左边的变量 是等待被赋值的 等号右边的变量 是取变量的值的 这个时候相当于使用变量 如果之前没有声明并赋予初始值 就会报错 ''' res = a + b print(res) s1 = "abc" s2 = "-def" res = s1 + s2 print(res, s1, s2, sep=" ") res = a * b print(res) res = s1 * 2 print(res, s1, sep=" ") x = 11 y = 2 print(x / y) print(x // y) print(x % y) print(x ** y) m = 10 n = 5 m **= n print(m)
16.2 关系运算符
经过关系运算符运算之后 最终的结果是bool类型的 > 大于 < 小于 >= 大于等于 <= 小于等于 == 是否相等 != 是否不相等 在数值中比较数值的大小 或者是否相等 在字符串中 比较方式 从第一个字符开始两者一一去对应比较的 本质上比较的是该字符对应的十进制数据 其中某个字符比较出来大小 比较结束
a = 10 b = 20 print(a > b) print(a < b) print(a >= b) print(a <= b) print(a == b) print(a != b) print("------------------------------") s1 = "abcd" s2 = "ab" print(s1 > s2) print(s1 < s2) print(s1 >= s2) print(s1 <= s2) print(s1 == s2) print(s1 != s2)
16.3 逻辑运算符
运算符两边绑定的数据是bool类型的 运算之后的结果也是bool类型的 逻辑与(and) 规则: 一假则全假 ===> and符号两边有一方为假False 结果就是False 逻辑或(or) 规则: 一真则全真 ====> or符号两边有一方为True 结果就是True 逻辑非(not) 规则: 真变假 假变真 ===> not后面的结果是True 最终结果为False not后面的结果是False 最终结果为True 优先等级: not > and > or 短路原则: 逻辑与and的短路原则: 根据一假则全假出现的 如果and左边的表达式不成立False 右边表达式不会被执行 如果后面有or的表达式 会直接执行or后面的内容 逻辑或or的短路原则: 如果or左边的表达式成立True 右边表达式不会被执行 根据这个规则出现一个语法: 三元运算符 值1和值2遵守的bool转换原则 这个三元运算符有弊端 变量名 = 条件表达式 and 值1 or 值2 条件表达式成立 执行值1 否则执行 值2 演示求两个数的最大值 以后使用三元运算符: 变量名 = 值1 if 条件表达式 else 值2
x = 0 y = -1 res = x > y and x or y print(res) res = x if x > y else y print(res)
16.4 成员运算符
针对于容器而言的 判断指定元素是否在指定的容器中 in 在的话为True 判断指定元素是否不在指定的容器中 not in 不在为True
s = "abcdef" list0 = ["a", "b", "c", "d"] res = "ba" not in s #不仅判断是否有这个字符 还判断顺序是否正确 print(res) res = "a" in list0 print(res)
16.5 身份运算符
验证变量的地址是否一致 is -- 地址一致结果为True is not --- 地址不一致结果为True id(数据) 获取数据的地址
16.6 位运算符
位运算符
针对于二进制数据的运算 二进制数据运算时是以补码的形态运算的 规则: 把1视作True 0视作False 二进制数通过运算符运算的时候 符号位也要参与运算的 以八位为例 按位与(&) 两个二进制数 上下一一对应参与运算 运算准则: 一假则全假 5&-7 5的补码: 0000 0101 -7的原码: 1000 0111 -7的反码: 1111 1000 -7的补码: 1111 1001 & 0000 0101 ------------------ 0000 0001 -----> 1 按位或(|) 两个二进制数 上下一一对应参与运算 运算准则:一真则全真 5 | (-7) 0000 0101 | 1111 1001 ---------------- 1111 1101 [补码] ----> -1求反码: 1111 1100 ----> 取反求原码: 1000 0011 [-3] 按位异或(^) 两个二进制数 上下一一对应参与运算 运算准则: 相同为假 不同为真 5 ^ -7 0000 0101 ^ 1111 1001 -------------- 1111 1100[补码] ---> -1求反码: 1111 1011 ----> 取反求原码: 1000 0100 [-4] 小知识点: 一个数与相同的数异或两次 结果是其本身 ----> 简单的小小的加密 密码: 123456 ----> 对应与一个数异或: 765489 用户输入123456 ---->验证的时候 异或一个对应的数据 与 存放的数据进行验证匹配 交换两个变量的值 a = 10 b = 20 ====> a = 20 b = 10 按位取反(~) 0变1 1变0 ~(-7) 1111 1001 ~ ----------------- 0000 0110 ----> 6 按位左移(<<) 将二进制数向左移动指定的位数 右边会空出 空出补0 1 << 3 ===> 1左移3位 0000 0001 结论: 原有的数据 * 2 ^ 移动的位数 按位右移(>>) 将二进制数向右移动指定的位数 左边会空出 正数补0 负数补1 32 >> 2 ====> 8 结论: 原有的数据 // 2 ^ 移动的位数 res= 5 & (-7) print(res) res= 5 | (-7) print(res) res= 5 ^ (-7) print(res) res = -4 ^ -7 # 5 ^ -7 ^ -7 print(res) a, b = 10, 20 # a, b = b, a # print(a, b) #因为当为a重新赋值的时候 a原来的值没有变量名接受了 所以这个数据就无法获取了 消失了 #先把a原来的值 使用另外一个变量名接受 # c = a # a = b # b = c # print(a, b) a = a ^ b b = a ^ b # b = a ^ b ^ b = a a = a ^ b # a = a ^ b ^ a = b print(a, b) res = ~-7 print(res) res = 1 << 3 print(res) res = 32 >> 2 print(res)
16.7 转义符
\ --- 具有转移的含义 可以使用其后面的字符失去原本意义 生成一个新的含义 \n -- 换行 \t --- 制表符 tab \r --- 回车 windows中表示换行的是 \r\n 如果以后写代码的时候 \n没有达到换行的效果 使用\r\n
17. 知识点–判断语句
三种: if单语句: if 条件表达式: [缩进tab]执行语句 --- 为什么要缩进? 执行语句是在满足if判断条件的情况下执行的 if-else if 条件表达式: 执行语句1 else: 执行语句2 如果条件表达式成立 执行语句1 否则执行语句2 ''' 键盘录入一个字符 如果是小写英文字母 将其转化为大写英文字母 否则 输入字符原本样子 ''' ch = input("请输入一个字符:") #方式1 # if 'a' <= ch <= "z": # print(chr(ord(ch) - 32)) # else: # print(ch) # # print("over") #方式2: data = ord(ch) if 97 <= data <= 122: print(chr(data-32)) else: print(ch)
17. 位运算符补充
位运算符
交换两个变量的值:[重点] 第一种方式: Python独有的: a , b = 10, 20 a, b = b, a #等号左边的变量 是等待被赋值的 右边的变量是取原来对应的数据的 第二种方式: 借助第三方变量 [JavaScript] 一般情况下应用于非Python的两个变量的交换 c = a a = b b = c 第三种方式: 使用异或的 一个数与相同的数异或两次 结果是其本身 [了解] 先将两个数进行异或 a = a ^ b b = a ^ b # b = a ^ b ^ b = a a = a ^ b # a = a ^ b ^ a = b
18. 模块与range功能的使用
模块 -----> 一个py文件就是一个模块 可以把模块当做一个工具箱使用
模块之间是可以互相访问的 访问的前提需要导入要使用的模块
自己定义的模块之间的访问
使用系统提供的模块 random 随机模块
range — 可以生成一个整数序列的功能
一个python文件就是一个模块 把他当做一个工具箱
不同的python文件是可以相互访问的 访问的前提需要导入使用模块
导入模块的格式:
import 模块名
使用模块中的内容的话 模块名.内容名
from 模块名 import 内容名字
====> 在指定模块中导入指定内容 使用内容的话 直接使用内容名
这种导入 只能使用该模块下你导入的内容名
from 模块名 import *
=====> 导入指定模块中所有的内容
可以直接使用该模块下的所有被__all__这个列表包含的内容,如果模块中没有设置__all__这个字段, 默认是使用所有
原生模块 random的使用 random这个是随机模块 --- 可以在指定的内容中产生随机数据 import random #1. 在指定的容器中随机选择一个元素 res = random.choice("abcdefghtyui") print(res) res = random.choice((12, 34, 65, 71)) print(res) #2. 在指定的整数范围内随机选择一个整数 #在指定的闭合区间中 随机的选择一个整数 [0, 1000] value = random.randint(0, 1000) print(value) #3. 在指定的整数范围内随机选择一个整数 前闭后开的区间 [start, end) value = random.randrange(1, 100, 2) # ====> value = random.choice(range(1, 100, 2)) #4.在指定的序列中选择指定个数的随机的功能 res = random.sample("1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM", 5) print(res) #使用列表容器存放产生的多个随机元素
range的使用 产生整数序列 help(功能) help(range) ''' range(stop) -> range object 传入一个结束值 区间的开始值是0 生成的这个区间序列 [0, stop) range(start, stop[, step]) -> range object 需要传入起始值 传入结束值 step表示的是步长 默认是1 如果传入step 会按照指定步长递增 或者 递减 生成的区间 [start, stop) ''' reslut = range(10) print(reslut) #将指定序列转化为列表 list(序列) ==> 将序列中的每一个元素存放于列表中 res_list = list(reslut) print(res_list) reslut = range(1, 10) #生成一个步长为1的序列 序列的起始值是1 res_list = list(reslut) print(res_list) reslut = range(1, 10, 2) #生成一个步长为1的序列 序列的起始值是1 res_list = list(reslut) print(res_list) #从10 -1 这种递减 10 9 8 7 6 5 4 3 2 1 reslut = range(10, 0, -2) #生成一个步长为1的序列 序列的起始值是1 res_list = list(reslut) print(res_list)
#设置外界使用模块内容的权限 __all__ = ["name", "add", "div"] name = "工具箱" #设置一个功能 函数的封装 计算两个数的和 ''' 一个: 是否有位置项参与功能的运算 有多少个 在函数名的小括号中写多少个变量名 2. 问一下 这个功能是否需要将结果返回给使用者 在函数中需要有return 一个返回 将结果返回给使用者 如果没有 return可以省略 或者 return None ===> 使用者获得的结果是None 函数格式: def 功能名字(接受未知项的变量名): 功能的实现 return 功能运算结果 ''' def add(a, b): total = a + b return total def div(a, b): return a / b #第一种导入方式 # import tool # # res = tool.name # print(res) # # res = tool.add(12, 16) # print(res) #第二种导入方式 # from tool import name, add # # res = name # print(res) # # #如果没有导入其他模块的内容 在当前模块中查找 # res = add(12, 34) #第三种导入方式 from tool import * res = name print(res) res = add(12, 45) print(res) res = div(12, 3) print(res)
练习: 1.使用range生成以下序列 -1 ~ -10 range(-1, -11, -1) 2.生成1-1000的序列 在该序列中随机选择3个数据 import random res_list = random.sample( range(1, 1001) , 3)
19. 流程控制语句
19.1 顺序语句
什么叫做语句??
在语法上自成体系的一个单位, 可能是一个词, 也可以能是通过逻辑关联的多个词
a:int
a = 10
在一般的编程语言中 语句结束的标志是分号(😉
在Python中语句结束的时候也可以以分号结尾 允许不写[建议不写]
什么情况下来写?? ----- 如果在一行中书写多条语句, 这个分号就不能省略了
建议 最好是一条语句占用一行
顺序语句的意思: 表示的是代码的执行顺序 是从上往下走的
print("hello") print("h"); print("b")
19.2 分支语句
分许需求的时候出现了不同的情况 — 出现了分支
出现了不同的情况 – 有可能会出现 —> 如果出现了 —> if
分支语句是if语句
if单语句 ---- 是一个整体 if 条件表达式: [缩进tab]执行语句 执行的流程: 判断条件表达式是否成立 成立的话 执行语句 if语句整体执行完毕 结束 向下执行与if平级的语句 不成立的话 if语句直接执行完毕 向下执行与if平级的语句 案例: 键盘录入一个整数 判断这个数是不是偶数 偶数的概念: 能被2整除 ---> 余数为0 num % 2 == 0
if-else语句 if 条件表达式: 执行语句1 else: 执行语句2 执行流程解读: 先判断条件表达式是否成立 如果成立的话 执行语句1 if-else整体结束 否则 执行语句2 if-else语句结束 案例:用户输入一个年份 验证这个年份是否是闰年 闰年的条件判断: 1.能被4整除 但是不能被100整除 year % 4 == 0 and year % 100 != 0 2.能被400整除 year % 400 == 0 1和2之间的关系 是满足其一即可 or year = int(input("请输入一个年份:")) if (year % 4 == 0 and year % 100 != 0) or year % 400 == 0: print(year, "是闰年") else: print(year, "不是闰年") print("验证完毕") import random 练习: 在1-100中随机生成两个数 前者>后者 计算两个数的差 否则计算两个数的和 import random num1 = random.randint(1, 100) num2 = random.randint(1, 100) print(num1, num2) if num1 > num2: c = num1 - num2 print(c) else: b = num1 + num2 print(b) print("结束") res = random.sample(range(1, 101), 2) a, b = res print(type(res)) if a > b: print(a-b) else: print(a + b) x = random.choice(range(1, 101)) y = random.choice(range(1, 101)) if x > y: print(x - y) else: print(x + y) x = random.randrange(1, 101) y = random.randrange(1, 101) if x > y: print(x - y) else: print(x + y)
if-elif-else语句 elif ===> else if的简写 注意: 只有 if如果的后面才会有条件表达式的判断 else是没有条件判断的 只有一个:跟随其后 if 条件表达式1: 执行语句1 elif 条件表达式2: 执行语句2 .... elif 条件表达式n: 执行语句n else: 上述列出的所有条件表达式都不满足 才会执行else 这多个if并联的是一条语句 满足其中一个条件 整体结束 案例: 猜字游戏 猜一次 系统随机生成一个50-300的整数 sys_num 用户输入一个50-300的整数 user_num 两个 比较大小 如果 用户 大于 系统 提示用户猜大了 否则如果 用户 < 系统 提示用户猜小了 否则 提示用户中奖了 import random sys_num = random.randint(50, 300) print(sys_num) user_num = int(input("请输入一个50-300的整数:")) #进行判定 if user_num > sys_num: print("猜大了") elif user_num < sys_num: print("猜小了") else: print("中奖了") print("游戏结束") 练习: 1.用户输入一个季节 根据季节输出对应的描述 春 ---- 万物复苏 夏 ---- 烈日炎炎 秋 ---- 硕果累累 冬 ----- 白雪皑皑 season = input("请输入一个季节:") if season == "春": print("万物复苏") elif season == "夏": print("烈日炎炎") elif season == "秋": print("硕果累累") elif season == "冬": print("白雪皑皑") else: print("输入正确的季节") 2.成绩等级划分 录入学生成绩 输出对应的等级 >= 90 A >= 80 B >= 70 C >= 60 D 其他 E grade=int(input("请输入学生的成绩:")) if grade>=90: print("A") elif grade>=80: print("B") elif grade>=70: print("C") elif grade>=60: print("D") else: print("E") print("请继续努力") 3.用户输入字符 如果是小写英文字母 --- 输出其对应的大写字母 如果是大写英文字母 ---- 输出其对应的小写字母 其他 输出字符本身 ch = input('请输入一个字符:') res1 = ord(ch) #获得字符对应的十进制数据 if 65 <= res1 <= 90: print(chr(res1 + 32)) elif 97 <= res1 <= 122: print(chr(res1 - 32)) else: print(ch) 或者 ch=input("请输入一个字符:") if "a"<=ch<="z": res=ord(ch) print(chr(res-32)) elif "A"<=ch<="Z": res1=ord(ch) print(chr(res1+32)) else: print(ch)
19.3 语句嵌套 - 符合所有的流程控制语句
分析逻辑的时候 在满足某种需求的情况下 又出现了逻辑判定
月份: 1 3 5 7 8 10 12 ----> 31 想要判定的话: 需要列出所有的满足31天的月份 查看你输入的月份是否在其中 在其中就是31天 month in [1, 3, 5, 7, 8, 10, 12] 31 month in [4, 6, 9, 11] 30 month == 2 需要判定年份 -- 是闰年(29)还是平年(28) 借助的成员运算符 将需要的数据存于容器中 判断指定数据是否在容器中 语句嵌套 ''' 语句嵌套 ''' month = int(input("请输入月份:")) year = int(input("请输入年份:")) if month in [1, 3, 5, 7, 8, 10, 12]: print(month, "有31天") elif month in [4, 6, 9, 11]: print(month, "有30天") elif month == 2: if year % 4 == 0 and year % 100 != 0 or year % 400 == 0: print(year, "年的", month,"月有29天") else: print(year, "年的", month, "月有28天")
20. 循环语句
循环: 重复做某件事情
没有终止的重复做某件事情, 这种循环称之为死循环
20.1 while循环机制
格式: while 条件表达式: 重复的功能 执行流程: 判断条件表达式是否成立, 如果不成立 循环语句直接结束 执行与while平级的语句 如果成立 执行重复的功能 ---> 再去判断条件表达式是否成立 如何达到死循环: 条件表达式一直成立的 写while循环的时候 明确条件: 1. 明确循环条件是什么 2. 重复做的事情是什么 案例: 以数数为例 数1-10 循环条件: 数据 <= 10 重复做的事情: 输出数据 对数据进行+1 ''' 要求: 只数1-10之间能被3整除的数 需要获取1-10之间的所有数 循环条件: 从1数到10 <= 10 重复做的事情 进行判断 是否能被3整除 --> 输出 对数据进行+1 ''' 练习: 1.求1-10的累加和 加 -- 累加 和 --- 需要用一个变量接收 声明一个变量 sum1 = 0 #在循环内声明还是在循环外声明 num = 1 sum1 = 0 #需要在外面声明 while num <= 10: #sum1 = 0 #如果是在这里面 每次循环都会将累计的和清零 sum1 += num num += 1 2.求1-10之间偶数的累加和 a = 1 sum1 = 0 sum2 = 0 while a <= 10: sum1 += a if a % 2 == 0: sum2 += a a += 1 print("1-10之间的累加和是", sum1) print("1-10之间的偶数的累加和是", sum2)
猜字游戏: 系统随机生成 50-300之间的一个数 用户去猜 循环的条件: 用户猜的 != 系统生成 重复的操作: 用户就得猜 用户输入 比较大小 对应提示 import random #系统随机生成 sys_num = random.randint(50, 300) print(sys_num) #在判断条件中使用user_num 给其赋值的位置却在使用之后 这种会出现错误 需要在使用之前先把该变量声明出来 #再使用之前 需要赋予初始值 初始值 需要满足 user_num不会与sys_num相等 user_num = None #重复的操作 while user_num != sys_num: #用户去猜 user_num = int(input("请输入50-300的数据:")) if user_num > sys_num: print("猜大了") elif user_num < sys_num: print("猜小了") else: print("中奖了") print("game over") ''' 格式化小键盘: 选中 -- tab -- 集体缩进 shit + tab ----> 反缩进 ''' while True: #用户去猜 user_num = int(input("请输入50-300的数据:")) if user_num > sys_num: print("猜大了") elif user_num < sys_num: print("猜小了") else: print("中奖了") #循环就可以结束了 break print("game over")
20.2 For循环机制
用于遍历序列的 容器的 格式: for 变量名 in 容器: 操作 for循环的遍历机制: 遍历的时候有一个遍历指针 指针的起始位置 在第一个元素的上方, 进行遍历的时候 先判断是否有下一个元素 如果有 指针向下移动一位 获取该位置的元素 赋予给变量 如果判断是否有下一位的时候结果是False, 遍历结束 使用forin完成数数 #遍历字符串 for ch in "abcdef": print(ch) for i in range(1, 11): print(i) print("-------------") #打印1-10之间的偶数 for j in range(1, 11): if j % 2 == 0: print(j) print("-----------------") #使用continue演示: 如果是奇数就跳过打印 for m in range(1, 11): if m % 2 != 0: break #print("a") print(m)
""" 日历是以1900年1月1日00:00:00为基础的 那天的星期一是已知的 万年历 a:先输入提示语句,并接受用户输入的年、月 b:根据用户输入的年,先判断是否是闰年。 c:根据用户输入的月来判断月的天数。 d:用循环计算用户输入的年份距1900年1月1日的总天数。 e:用循环计算用户输入的月份距输入年份的1月1日共有多少天。 f:相加D与E的天数,得到总天数。 g:用总天数来计算输入月的第一天的星期数。 h:根据G的值,格式化输出这个月的日历! 换行的时候的规则: (空格数 + 日期号) % 7 == 0 0 0 0 0 1 2 3 4 5 6 7 8 9 10 """ ''' 1.验证指定年是否是闰年 ''' def is_leap(year): if year % 4 == 0 and year % 100 != 0 or year % 400 == 0: return True else: return False ''' 2.获得指定月的天数 ''' def get_days(month, year): if month in [1,3, 5, 7, 8, 10, 12]: return 31 elif month in [4, 6, 9, 11]: return 30 else: return 29 if is_leap(year) else 28 ''' 3. 获得指定年到1900年经历了多少天 ''' def get_year_days(year): year_days = 0 for y in range(1900, year): year_days += 366 if is_leap(y) else 365 return year_days ''' 4.获得指定到到当前年1月经历了多少天 ''' def get_month_days(month, year): month_days = 0 for m in range(1, month): month_days += get_days(month, year) return month_days #键盘录入年 和 月 year = int(input("请输入年份:")) month = int(input("请输入月份:")) #获得这个月的天数 days = get_days(month, year) print(days) #获取总天数 total_days = get_year_days(year) + get_month_days(month, year) + 1 #这个1是进入指定月份的第一天 #获取这个月的第一天对应的星期数 week = total_days % 7 #星期几 print(week) print("星期日\t星期一\t星期二\t星期三\t星期四\t星期五\t星期六") #真正的日期前面有空白站位 #打印空白 for s in range(week): print("\t\t", end="") #打印真正的日期 for d in range(1, days + 1): print(d, end="\t\t") if (week + d) % 7 == 0: print()
20.3 关键字的使用
break 只对循环语句起作用 作用是结束其当前所在的循环语句 就近原则: 只结束离他最近的循环语句 continue 只对循环语句起作用 作用: 结束当前次循环 继续下一次 在遍历的时候遇到continue 会中断该次的遍历 回到循环条件判断的位置 如果判断成立 执行下一次循环 注意: break 和 continue后面 不要添加与其平级的任何语句 因为这些语句永远不会被执行 # isrunning = True # while isrunning: # while True: # if True: # isrunning = False # break 当嵌套了两个while循环语句的时候,break只能结束离他最近的while语句,外面的语句没有办法终止
20.4 while循环跟for循环详解
while循环 -- 使用场景在明确循环条件的情况下 while循环 break continue 都是作用于就近的循环 while 条件表达式: 重复的操作 另外一个格式: while 条件表达式: 重复的操作 else: 当且仅当 while的条件表达式不成立的时候 才会执行else,如果是break导致的while强行结束不会执行到else语句 -------------------------------------------------------------------------------- #数数 1-10 num = 1 #数到5之就不数了 while num <= 10: print(num) num += 1 if num > 5: break else: print("条件不成立了") print("数完了")
for循环 ----> 使用场景 遍历序列 for 变量名 in 序列: 重复的操作 另外一种格式: for 变量名 in 序列: 重复的操作 else: 当且仅当 序列中元素全部遍历结束的时候 才会执行else 案例: 判断一个数是不是质数(素数) 质数的概述: 只能被1和本身n整除 整除的判定的时候: 如果这个数被 2 ~ n/2之间的数整除 ----> 这个数不是质数 for i in range(2, (n)//2+1): if n % i == 0: #代表这个数不是质数 break #当只要在这个中 被整除1次 就已经不满足条件了 其他的数据没有必要再去验证 else: #这个数是质数 特殊的数据 6 [2, 3] 特殊的数据 9 [2, 3, 4] 特殊的数据 11 [2, 3, 4, 5] 分析: 当从头到尾遍历完成 if条件都不成立 --- 这个数才是质数 #先不考虑 特殊数据是1 --- 什么都不是 n = int(input("请输入一个整数:")) if n <= 1: pass #空白站位符 在缩进的语句中不知道该做些什么操作 但是缩进语句又不能不写内容 用pass来站位就行 else: for i in range(2, n // 2 + 1): #如果是2的情况下 [2, 2) [2, 3) [2, 4) if n % i == 0: print(i) print(n, "不是质数") break else: print(n,"是质数")
注意: 循环的话导致程序在循环的位置 一直执行 知道循环结束 程序才会继续向下进行 循环嵌套这里的建议: 嵌套的层数最好不要超过3层, 如果循环次数过多, 占用内存, 如果内存占用过多 程序会卡死 甚至崩溃
21. 函数
21.1 什么叫做函数
在程序中独立存在一段代码, 一个功能. 又称之为方法
函数的作用:
将常用的代码 封装成功能, 使用该代码的时候直接调用功能, 便于简化代码, 减少代码的重复率
函数的分类:
系统提供的内置函数
例如: 输出功能print 输入功能input
自定义函数
根据需求自定定义的一个功能
案例:求圆的面积 公式: π *r ** 2 π默认取的是3.14 需求: 求半径为5的面积 s = 3.1415926 * 5 ** 2 求半径为10的面积 s = 3.1415926 * 10 ** 2 求半径为20的面积 s = 3.1415926 * 20 ** 2 需求: 精确圆周率 将圆周率改为3.1415926 单独封装成功能 - 求指定半径的圆的面积 def area(r): s = 3.14 * r ** 2 return s area(5) area(10)
21.2 自定义函数的格式
def 函数名(设置的接收参与功能未知项的变量名): 函数功能 return 功能运行的结果 解释: def ---- 自定义函数的一个关键字 函数名 ---- 自定义功能起的名字 需要遵守标识符规范 命名规则:英文字母都是小写 每个单词之间使用下划线隔开 例如: get_max_value ()小括号中的变量名: -----> 形式参数 ----> 简称形参 作用: 是用于接受参与功能运算的数据 有多少个未知的数据参与功能运算 ,就得声明几个形参, 每个形参之间使用逗号分开 如果没有未知项参与运算 小括号也不能省略 必须存在的 例如: 求圆的面积 def area(r): pass 求两个数的和 def add(a, b): pass 实际参数 -----> 简称实参 使用者调用功能时 向功能运算中传递的数据 是给形参赋值的 return ----> 结束函数 并将结果返回给使用者 如果自定义的功能没有结果返回 return语句可以省略 或者 写为 return None [这两种写法都是向调用者返回一个空值None]
最好做到两个明确: 1. 明确这个功能是否有未知项参与运算 有几个?? ----> 完成形参的设置 2. 明确这个功能是否需要将结果返回给使用者 -----> 是否需要书写return
return 和 print的区别: return只能应用于函数中 作用是结束函数 把结果返回给使用功能的地方 print 输出语句 可以应用于任何位置 把你想要输出的结果输出到控制台
1. 判断两个数是否相等 未知项: 两个 需要把结果返回 ----> 最好返回的是bool类型 def is_equal(a, b): # if a == b: # return True # else: # return False #return True if a == b else False return a == b 2.比较两个数的大小 前者>后者 返回1 前者<后者 返回-1 否则返回 0 def compare(a, b): if a > b: return 1 elif a < b: return -1 else: return 0 3. 封装一个功能: 打印九九乘法表 调用功能 -- 控制台上出现九九乘法表 def print_nine_table(): for r in range(1, 10): for c in range(1, r + 1): print(c, "*", r, "=", c*r, end="\t") print() 4. 封装一个函数: 打印指定行数的乘法表 3 ---> 1 ~ 3 4---> 1~4 def print_table(line): for r in range(1, line + 1): for c in range(1, r + 1): print(c, "*", r, "=", c * r, end="\t") print() 5. 封装一个函数 验证制定年是否是闰年 def is_leap(year): if year % 4 == 0 and year % 100 != 0 or year % 400 == 0: return True else: return False 6.封装一个函数 获取指定月的天数 def get_days(year, month): if month in [1, 3, 5, 7, 8, 10, 12]: return 31 elif month == 2: return 29 if is_leap(year) else 28 else: return 30
使用功能: 函数名(实际参数) 如果功能有结果的返回 可以使用一个变量接受结果 注意: 声明函数时有多少个形参 就得传递多少个实参 而且两者是一一对应的
22. 变量的分类
变量的分类: 全局变量 和 局部变量
全局变量:在非函数中声明的变量 都是全局变量 全局变量的特点: 只要声明出来 在声明之后的任何位置都可以使用 局部变量: 在函数中声明的变量[包含形参和在函数体中声明的变量] 特点: 作用范围仅限于在函数体中 出了函数体没有任何意义 在函数中声明一个变量 如果这个变量与全局变量重名 作用范围采用就近原则 如果想让函数中声明的变量 使用就是全局变量的哪个作用范围 需要在函数中对该变量进行一个修饰 告知解释器这个变量的范围为全局变量的范围 修饰符号 global 在使用之前进行修饰 global 变量名
23. 方法的执行流程
内存结构: 内存结构中划分了不同的区域 栈区 堆区 方法区 本地方法区 寄存器(什么数据存于寄存器中是由CPU决定的) ----------------------------------------------------------------------------------- 方法区(与程序共存亡的): 属于共享区域 有划分了3个部分: 常量池: 存放的数值类型数据 和 字符串类型的数据 存放的特点: 将常量池中的数据赋值给变量, 先在常量池中查找是否有该数据, 如果有的话 会直接将该数据的地址赋值给变量, 如果没有先在常量池中开辟空间存放数据, 再将对应的地址赋予给变量 静态池: 存放这全局变量 和自定义类型中类变量 方法池 声明的方法 都存放与方法池中 ----------------------------------------------------------------------------------- 栈区: 存放正在执行的方法和局部变量, 将方法池中的方法拷贝一份存放于栈中 进而去执行 栈的特点: 先进后出 方法执行完成 会立即被销毁 空间立即释放出来 ----------------------------------------------------------------------------------- 堆区: 存放的是非(数值类型和字符串类型)的数据 特点: 每生成一个新的数据 都有自己独特的地址 即使数据外表看起来一样 释放内存的时机: 当数据没有变量名指向的时候 会被标记上垃圾的标识, 有Python垃圾回收机制将其回收
24. 默认参数
在调用函数时 给某个形参赋值时 值通常情况下是固定的 但是也有特殊的情况 这种情况下就可以将对应的形参赋予一个常用的默认值, 再调用函数时 如果需要的是这个默认值 就可以不用给该形参赋值, 如果是其他特殊值可以给该形参再重新赋值 例如: 输出功能中 多个打印的数据之间的分隔符 默认是空格 打印结束之后 的结束符 默认是换行 例子: 求x的y次方 常用的情况下是求x的平方 ''' 默认参数 ''' ''' 例子: 求x的y次方 常用的情况下是求x的平方 ''' def power(x, y=2): return x ** y res = power(2, 2) print(res) res = power(3) print(res) res = power(4, 3) print(res)
25. 递归算法
#在功能内部直接使用功能本身 算法: 前辈们已经总结好的解决某种问题或者逻辑思路的一种方式 递归算法: 在函数体中调用函数本身 这种情况就是递归算法 斐波拉契数列 假设初始第一个月的时候有一对兔子, 从第三个月开始这对兔子每个月生一对小兔子, 小兔子从出生的撕单个月开始 每个月生一对小小兔子, 问8个月后兔子总共有多少对 已知项: F(1) = 1 F(2) = 1 F(n) = F(n-1) + F(n-2) n>=3 注意事项: 1.递归必须得有出口 - 功能的已知项 否则会造成栈溢出RecursionError: maximum recursion depth exceeded 2. 递归的层次不能太深 [调用的时候 一层一层的压栈 -- 就有有可能出现栈溢出] 递归来完成练习: 1.求出1-指定数之间的累加和 指定数是必须>1 F(1) ----> 1 F(2) -----> 2 + 1 = 2 + F(1) F(3) -----> 3 + 2 + 1 = 3 + F(2) F(n) = n + F(n-1) 2.求出指定数的阶乘 5! = 5 * 4 * 3 * 2 * 1 F(1) = 1 F(2) = 2 * 1 = 2 * F(1) 映射: F ----> 函数名 (n) ----> 形参 =号后面的内容 就是return的结果 ''' F(n) = F(n-1) + F(n-2) n>=3 F(1) = 1 F(2) = 1 ''' def F(n): # n = 3 if n in (1, 2): return 1 else: return F(n-1) + F(n-2) res = F(3) print(res) def get_sum(num): if num == 1: return 1 else: return num + get_sum(num-1) # 3 + get_sum(2) # 3 + 2 + get_num(1) res = get_sum(3) print(res) def mul(num): if num == 1: return 1 else: return num * mul(num - 1) res = mul(5) print(res)
26. 可变参数*args
#传递给函数的实际参数个数是可变的---args 声明的函数的时候: 明确有几个未知项参与运算 有几个声明几个 -- 形参的个数 函数调用的时候 有几个形参 传递对应的实参 但是有些情况下 参与功能运算的未知项的个数不能确定 这个时候就可以把形参设置成可变参数 可变参数声明格式: 在形参变量名前添加* def 函数名(*变量名): 函数功能 return 结果 案例: 计算n个数的和 def get_sum(*nums): #nums需要是一个容器 才可以接受多个数据 #<class 'tuple'> print(type(nums)) print(nums) #求和 total = 0 #遍历元组 for n in nums: total += n return total #经常使用的状态 res = get_sum(121, 13, 56, 78) print(res) 调用函数时 函数名(实际参数1, 实际参数2, ... 实际参数n) 每个实际参数之间使用逗号隔开 可变参数经典案例: print(*values, sep=" ", end="\t") 在可变参数中使用的是一个元组类型的容器 存放使用者传递过来的多个数据
练习: 1.求n个数的累乘 def get_mul(*nums): #声明一个变量 接受累乘的结果 result = 1 #遍历nums容器中的每一个数据 将其与result累乘 for i in nums: result *= i return result res = get_mul(2, 45, 9) print(res) 2.声明一个功能 可以接受任意个数据 获得这些数据中的偶数 容器存放需要获取的数据 def get_even_num(*values): #因为偶数可能有多个 都需要获取出来 所以需要一个容器来存放这个偶数 odd_list = [] for num in values: if num % 2 == 0: odd_list.append(num) return odd_list
27. 关键字参数**kwargs
使用者调用函数时 实参的个数要与形参的个数一致 并且两者是一一对应的 #获得指定月的天数 def get_days(month, year): if month in [1, 3, 5, 7, 8, 10, 12]: pass #调用函数的时候 get_days(3, 1960) 如果形参个数较多, 顺序记得不太清除 可以使用关键字形式传递实参 调用函数的时候: 函数名(形参名=实参数据, 形参名2 = 实参数据) 针对于函数声明的: 可以借助于注册账户的时候 有必填项和选填项 必填项的字段 非常明确的 --- 声明在函数中 形参字段 明确的 选填项用户可以传 也可以不传 字段的有无就不明确了 但是如果有的话 服务器端就得保存下来 字段声明或者不声明就不明确了 -- 声明成关键字参数 web网站 --- 服务器端 --- 服务于用户的 存储用户的数据 给用户发送对应的数据等 客户端和服务器端交互的时候 服务器接收客户端数据就通过函数调用来接收了 讲一个形参设置为关键字参数的方式: 在变量名前面加** def 函数名(**kwargus): pass #函数中 kwargus是字典类型的 接收用户数据时 用户传递数据的格式: 函数名(key=value, key1=value1)
def get_days(month, year): if month in [1, 3, 5, 7, 8, 10, 12]: return 31 elif month in [4, 6, 9, 11]: return 30 elif month == 2: if year % 4 == 0 and year % 100 != 0 or year % 400 == 0: return 29 else: return 28 else: print("请输入正确的月份") return 0 res = get_days(year=1997, month=3) print(res) 这里年和月调换了位置,采用了关键字参数year=199,month=3来实现位置的调换
28. 偏函数
因为一些函数是具有默认值的 这些默认值是在通常使用的情况下允许的 但是有些情景下常用的是另外一种值, 这个默认值在使用的时候就需要给每次进行赋值 可以借助自己的方法或者系统提供的机制 生成一个新的函数 采用的是新的默认值 这种函数就叫做偏函数 例如: print(sep=" ") #空格是默认使用场景下的 现在需要分割符 是*号 print(sep="*") 修改方式有两种: 1.自定义一个方法 在这个方法调用原本函数本身 修改函数的默认值 2.使用系统提供的一种机制 需要导入模块functools 有一个功能可以重新设置函数的默认值 并生成一个新的对应的函数 import functools cus_p=functools.partial(print,sep="*")(函数可以当作值被赋予给其他变量) 调用时可以直接使用:cup_s(10,20)
函数可以当做值赋予给其他变量 # b = print b("a", "b") #如果带小括号的话,就是讲print的值赋予给 b b=print() 这种情况下 b就有了与print一样的功能 可以向print一样去打印 赋值的时候注意: 函数当做值来赋予的时候 赋予的是函数名 不要加小括号 加上小括号是调用函数 是把函数的运行结果赋予给了变量
29. 匿名函数
常用于一些系统提供的方法中的为指定接收函数的形参赋值的 可以简化一些简单的函数 如果这个函数 功能中只有一个表达式 并且这个表达式的结果就是函数的运行结果 就可以把这个函数简化成匿名函数 def 函数名(形参): return 结果 匿名函数的格式: lambda 形式参数1, 形式参数2,..形式参数n : 表达式结果 例如: 求两个数的和: def add(a, b): return a + b ====> lambda a, b: a + b 匿名函数如果没有变量值来接受该函数 他只会被执行1次 便在内存中消失了 匿名函数的执行: res = (lambda a, b: a + b)(实际参数1, 实际参数2)
def add(a, b): return a + b res = add(12, 34) print(res) #匿名函数 res = (lambda a, b: a + b)(34, 56) print(res) ''' 函数可以当做值被付给其他变量 ''' f = lambda a, b: a == b res = f(15, 14) print(res)
30. 闭包
函数嵌套 在一个函数中声明另外一个函数 这种函数嵌套的格式 称之为闭包 def 外部函数(形参): def 内部函数(形参): pass 在内部函数中可以使用外部函数的变量, 但是如果在内部函数中声明了一个与外部函数同名的变量, 内部函数的变量的作用范围采用就近原则 仅作用于内部函数 与外部函数的变量只是重名了而已 在内部函数中想要修改外部函数的变量的值 需要在内部函数中对该变量进行修饰 nonlocal非本地变量修饰 只有这样才可以将内部与外部函数同名的变量关联起来
'''' 需求 在外部函数outer1的外部调用 内部函数 inner1 直接调用完成 不了 -- 间接调用 间接调用: 将外部函数的返回值设置为内部函数 ''' def outer1(): print("这是外部函数") def inner1(): print("内部函数") return inner1 res = outer1() print(res) #想运行inner1就是运行res res()
''' 闭包 ''' def outer(): num = 100 print("这是外部函数") def inner(): nonlocal num num = 200 print("这是内部函数") print(num, "内部函数的num") inner() print(num, "外部函数的num") outer() ''' inner的使用范围是什么?? 在outer的外部可不可以调用inner inner的使用范围仅限于在outer内部 函数拥有自己独立的作用域 -- 这个作用域与外界互不干扰 在函数内部声明的内容 只能在函数内部使用 ''' '''' 需求 在外部函数outer1的外部调用 内部函数 inner1 直接调用完成 不了 -- 间接调用 间接调用: 将外部函数的返回值设置为内部函数 ''' def outer1(): print("这是外部函数") def inner1(): print("内部函数") return inner1 res = outer1() print(res) #想运行inner1就是运行res res()
31. 装饰器
装饰器: 在不修改原有功能/类的基础上 为他们增加额外的新的信息 不加装饰器: 获取的功能的本身操作 加上装饰器之后: 不仅有本身的操作 还有新的信息展示 例如: 家中的吊灯: 发光的本质 ---- 灯泡本身 为了好看 会给他添加修饰 -- 但是这些修饰只是在发光的本质上增加的额外的内容 反应的程序中: 修饰的内容 --- 使用特殊的闭包[将内部函数当做外部函数的返回值]来体现的 装饰器的闭包的写法: def 外部函数(外部函数的形参): def 内部函数(内部函数的形参): 一系列操作 return 内部函数 讲解: 外部函数的形参接受的是 被修饰的函数 为原有功能添加装饰器的语法: 语法糖 @语法 @外部函数名 def 原有功能(): pass 装饰器时可以为所有功能添加装饰的 添加装饰器的时候闭包的完整格式: def 外部函数名(接受被装饰的函数的变量名): def 内部函数名(*values, **kwargs): 添加的装饰部分 result = 真正功能执行(*vlaues, **kwargs) return rerult return 内部函数名 给一个功能添加装饰的时候 @外部函数名 --- 有这个装饰的时候 调用被修饰的函数名执行方法 结果中既包含原有功能的实现 又有被装饰的内容出现 如果没有这个装饰 调用被修饰的函数名执行方法 执行的原有功能的本身 知识点: 为一个功能添加装饰器后 该装饰器的外部函数只会被执行1次 执行时机是@语法糖的时候 --- 学习自定义类的时候 ---设计模式:单例类 --- 用到了这个知识点 练习: 借助装饰器 是一个功能只会被执行1次 第一次执行有对应的结果出现 之后的每一次运行 获取的都是第一次的结果 def add(a, b): return a + b res = add(12, 12) ===> 24 res = add(12, 34) ===> 24 def single_run(func): #借助的是外部函数只会被执行1次 result = None #这一执行完1次之后 不会再有被重置的可能了 def inner(*values, **kwargs): nonlocal result if result == None: result = func(*values, **kwargs) return result return inner @single_run def add(a, b): return a + b res = add(12, 34) print(res) res = add(13, 34) print(res) res = add(15, 34) print(res)
装饰器: 本质上就是一个函数, 可以让其他函数在不需要更改任何代码的情况下增加额外的功能 装饰器的返回值: 是一个函数 装饰器在书写的时候 是一个函数嵌套的格式 #简单的装饰器的书写 def out(func): def inner(): func() return inner 想将装饰器中额外的功能给指定函数添加 在指定函数声明的上方 @out 当你@的时候 装饰器的外部函数执行了 保持一个为原有功能添加额外功能之后 原有函数名不变 #这个代码是解释器执行的 原有函数名 = out(原有功能名字) 程序员只需要@即可 上面的代码会自动完成 调用函数的时候 怎么调用 --- 就像没有添加装饰器格式调用即可 @out def add(a, b): return a + b res = add(11, 22) #有无装饰器 调用的始终是原有函数名
def single_run(func): #借助的是外部函数只会被执行1次 result = None #这一执行完1次之后 不会再有被重置的可能了 def inner(*values, **kwargs): nonlocal result if result == None: result = func(*values, **kwargs) return result return inner @single_run def add(a, b): return a + b res = add(12, 34) print(res) res = add(13, 34) print(res)
#功能: 打印九九乘法表 # def print_table(): # import time # start = time.time() # for r in range(1, 10): # for c in range(1, r + 1): # print(c, "*", r , "=", c * r , end="\t") # print() # stop = time.time() # print("执行时间:", stop - start) def print_table(): for r in range(1, 10): for c in range(1, r + 1): print(c, "*", r , "=", c * r , end="\t") print() # print_table() ''' 看一下这个功能执行需要多长时间 需要一个模块 time time() --- 获取当前时间的时间戳 不修改原有功能 ----> 可以单独写一个方法----> 计算指定功能运行时间的 ----> 有一个未知项 ---> 待计算时间的功能 ''' def get_time(func): import time start = time.time() func() stop = time.time() print("执行时间", stop - start) #查看执行时间 get_time(print_table) print_table() ''' 要求 执行函数本身 print_table既能实现原有的功能 又能计算执行时间 ---- 装饰器 '''
练习
1.封装一个功能 可以接受任意个参数 获取传入数据中的所有奇数 def get_odd_nums(*values): #values中可以存放多个数据 --- values对应的类型 是一个容器 print(type(values)) #tuple print(values) #获取所有的奇数 -- 需要一个容器来接受存放 -- 容器随着遍历vlaues长度是可变的 odd_list = [] #遍历 for v in values: print(v) if v % 2 != 0: odd_list.append(v) #遍历完成 所有的奇数都找到了 return odd_list res = get_odd_nums(13, 56, 78, 10, 19) print(res) 2.列表中的数据为 list0 = ["hello", "nice", "family", "you"] 根据字符串长度 获取列表中长度最大的字符串 list0 = ["hello", "nice", "family", "you"] max_str = max(list0, key=len) print(max_str) ''' key -- 设置按照指定的标准 取比较序列中/多个数据中元素的大小 key这个函数返回的是一个比较的标准 按照这个标准 比较序列中/多个数据中元素的大小 返回的对应序列中/多个数据中的最值 一般情况key默认是None 比较的标准是数据的原本大小 key接受的一个函数 --- 这个函数必须有返回值 将序列中/多个数据依次传入到函数中 根据函数返回值 作为一个比较的标准 取对元素进行比较 按照该标准获得对应的最值 ''' max_value = max(13, 45, 71, 28, -89) print(max_value) max_value = max(13, 45, 71, 28, -89, key=abs) print(max_value) 3.设计一个装饰器 装饰器的功能是 可以计算出一个功能的执行时间 def get_time(func): #func ---> 接受被装饰的函数的 def inner(*values, **kwargs): import time start = time.time() result = func(*values, **kwargs) #在额外增加的功能中嵌套着原有功能的实现 stop = time.time() print("执行时间:", stop - start) return result return inner ''' 执行了装饰器的外部函数 add = get_time(func = add) #保持的是原有函数的函数名不变 调用函数的时候一 直使用原有的函数名进行调用 没有添加装饰器 --- 调用的函数功能本身 添加了装饰器 -- 调用了装饰器中的内部函数 ''' @get_time def add(a, b): return a + b res = add(12, 45) print(res) ''' 没有添加装饰器 执行的就是函数的本身 添加了装饰器 -- 已经把函数本身传入到装饰器中了 add = get_time(func = add) 添加了装饰器 不仅要执行函数本身的功能 还要执行装饰的内容 装饰的内容在装饰器的内部函数中封装者 ----. 所以需要去执行内部函数 如何执行内部函数: 执行外部函数的时候 将内部函数返回出来了 装饰器保持着原有的功能的函数名不变的本质 所以接受 内部函数的时候 使用与原有功能同名的变量名来接受的 add = get_time(add) 这个时候 add被重新赋值了 等价于内部函数 所以添加上装饰器之后 再使用原有函数名来调用函数的话 其实调用的是内部函数 '''
32. 数据类型详解
数值类型
字符串数据类型
列表数据类型
有一些算法需要掌握:
排序算法
查找算法
32.1 数值类型
数值类型中:
整型int 浮点型float 复数型complex
系统提供的操作数据的方式 ------------------------------------------------------------------------------------ 1. 比较两个数的大小 python2.x中 cmp(x, y) x > y 返回的是1 x < y 返回的是-1 x == y返回的是0 python3.x舍弃了上述方法: 提供了另外一种方式: 在这种方式中将True视作1 将False视作0 (x > y) - (x < y) #1. 比较两个数的大小 a, b = 17, 24 res = (a > b) - (a < b) print(res) ------------------------------------------------------------------------------------ 2.求绝对值 abs(数据) #2.求绝对值 res = abs(res) print(res) ------------------------------------------------------------------------------------ 3.四舍五入 round(number[, digit]) number 要进行四舍五入的数据 digit 表示进行四舍五入之后 保留小数的个数 digit默认是0 res = round(3.54) print(res) res = round(3.547, 2) print(res) ------------------------------------------------------------------------------------ 4.求指定数的幂数 pow(x, y) x ** y #指定数的幂数 res = pow(2, 4) print(res) ------------------------------------------------------------------------------------ 5. 求序列中或者多个数据值中的最值 max(序列/多个数据, key=函数) 求最大值 min(序列/多个数据, key=函数) 求最小值 key接受的是一个函数, 将序列或者多个数据依次作用于函数 根据函数的返回结果进行比较获取序列/多个数据中的最值 key可以不传值 默认为None 这种情况下是根据数据的真正大小比较的 #求最值 max_value = max(23, 71, -15, -89) print(max_value) #根据数据的绝对值的结果 获得对应的最值 ''' 将多个数据中的每个数据都在abs中运行 根据获得结果中的最值 找到在原有的数据中对应的数据 或者 以绝对值的形式比较数据的大小 获取对应的原有数据的最值 [23 71 15 89] ''' max_value = max(23, 71, -15, -89, key=abs) print(max_value) max_value = max([34, 56, 71, 25]) print(max_value) ''' 如何获得序列中的最值??? 1.按照元素大小取比较 直接获取的最值元素 2.根据脚标对应的元素进行比较 获得最值对应的脚标 根据这个脚标获得元素 ''' ------------------------------------------------------------------------------------ 模块math --- 是针对于数学的函数功能 三角函数 import math #1. 向上求整 >= 指定数据 离指定数据最接近的整数 res = math.ceil(18.1) print(res) #2. 向下求整 <= 指定数据 离指定数据最接近的整数 res = math.floor(18.9) print(res) # res = math.log2(16) print(res) #开平方 res = math.sqrt(9) print(res) #圆周率 print(math.pi) res = round(math.pi, 3) print(res) print(type(res))
32.2 字符串数据类型
字符串对应的类型名字: str 字符串是存放的一系列字符的容器, 在字符串中存放的字符都有自己的编号 这个编号是从0开始的 注意: 字符串的内容是不允许发生变化的, 如果发生变化是新生成了另外一个字符串 与原来的字符串无关
常用方法
s = "good good study" -------------------------------------------------------------------------------- #1.获得字符串的长度 length = len(s) print(length) -------------------------------------------------------------------------------- #2.在字符串中每个字符都有自己对应的索引 ''' 索引有两种表示方式 1. 从0开始的 到len(s)-1 [0, len(s)-1] 2. 从-len(s) 到 -1 [-len(s), -1] ''' #获取第一个字符: ch = s[0] print(ch) ch = s[-length] print(ch) #注意索引范围 防止索引越界 # ch = s[length] #IndexError: string index out of range # print(ch) #字符串的内容一旦确定不能再发生改变 # s[0] = "G" #TypeError: 'str' object does not support item assignment 字符串的元素不允许被再次赋值 # print(s) -------------------------------------------------------------------------------- #3.切片 ---- 提取子串 ''' [start:stop[:step]] start 和 stop控制的是索引 索引是按照指定数据递增的 start stop step数据都可以省略 但是:不允许省略 与步长绑定的冒号可以省略 步长省略 默认值为1 start数据省略 默认是从头开始读取 stop省略 默认是到尾结束 如果设置stop ----> 提取的范围: [start, stop) ''' sub_s = s[:] print(sub_s) #设置步长 步长前面的:必须存在 sub_s = s[::2] print(sub_s) #可以设置步长为负数 start 和 stop不赋值 可以生成字符串反转 sub_s = s[::-1] #===> s[-1:-len(s)-1:-1] print(sub_s) sub_s = s[-1:-len(s)-1:-1] #[::-1]是这个式子的简写 print(sub_s) sub_s = s[:5] print(sub_s) sub_s = s[5:] print(sub_s) -------------------------------------------------------------------------------- #4.获得字符串中指定字符出现的次数 ''' 指定字符串 字符串接受者.指定的功能 ''' s = "kkkabcdkkkk" #从头到尾找连续的字符 如果字符之前找过 不会再列入重找 num = s.count("kk") print(num) #从某个位置{表示的是索引}开始查看某个字符串出现的次数 num = s.count("kk", 5) print(num) #指定区间范围 在区间范围内查找指定符出现的次数 # [start, stop) num = s.count("kk", 5, 9) print(num) -------------------------------------------------------------------------------- s = "nice to meeto you too" #5.查找指定字符第一次出现的位置 # 如果找的是多个连续字符第一次出现的位置 返回的是连续字符中第一个字符对应索引位置 #index --- 找到返回索引位置 找不到报错 # index = s.index("top") #ValueError: substring not found # print(index) #find --- 常用 找到返回对应的索引位置 找不到返回-1 index = s.find("to") print(index) #指定起始位置开始查找 index = s.find("to", 6) print(index) #指定范围查找 index = s.find("to", 6, 19) print(index) #指定字符最后一次出现的位置 index = s.rfind("to") print(index) #指定范围去查找 index = s.rfind("to",0, 18) print(index) s = "nice to meeto you too" ''' 从第一次出现的t 开始 提取之后的子串 [包含t] ''' sub_s = s[s.find("t"):] print(sub_s) -------------------------------------------------------------------------------- s = "nice to meeto you too" #6.字符串切割 -- 以指定的切割符为切点 将字符串分成对应的子串 --- 返回结果是列表类型的 ''' 字符串.split(["指定切割符"]) 不设置切割符 默认是以所有的空白字符序列[print打印的时候显示出来的是空白]为切割符 " " "\n" "\r" "\t" 在结果中产生的空字符序列会被移除 ''' sub_list = s.split(" ") print(sub_list) sub_list = s.split("o") print(sub_list) ''' nice to meeto you too 第一个 ====> nice t, meeto you too 第二个 ====> meet, you too 第三个 ====> y, u too 第四个 ====> u t, o 第五个 ====> "", "" ''' s = "\n你好\n我好\n大家好\n" res = s.split() #["","你好","我好", "大家好", ""] print(res) -------------------------------------------------------------------------------- #7.字符串格式化 #7.1. 想保持字符串原样输出 ====> 多行注释 就是一个字符串 s = ''' nice to meeto you too 第一个 ====> nice t, meeto you too 第二个 ====> meet, you too 第三个 ====> y, u too 第四个 ====> u t, o 第五个 ====> "", "" ''' print(s) #7.2.包含特殊字符 --- 转义符 ''' \ --转义符 可以将其后面的字符更改意义 例如 \n \t 有一些情况下 需要保持n或者t的本意 \\n ----> 设置一个文件路径 文件路径的分隔符 \ 借助于r 在字符串前面添加r修饰符 可以保持\的本意 ''' path = "C:\\Documents\\讲课内容\BJPython1901\day06\\notes" print(path) path = r"C:\Documents\讲课内容\BJPython1901\day06\notes" print(path) #7.3输出的字符串 的内容中 需要包含引号 ''' 你好 ---> 'hello' 方式1. 如果输出的引号是单引号 最外层使用双引号包含 方式2: 使用\进行转义 ''' s = "你好 ----> \"hello\"" print(s) #7.4format ''' 键盘录入姓名和年龄 --- 输出的格式是 我的姓名是xxx, 年龄是xx ''' name = input("请输入姓名:") age = int(input("请输入年龄:")) # print("我的姓名是",name,", 年龄是",age, sep="") ''' format格式化的方式 先把想要的字符串格式写出来 在未知项的地方使用{}占位, 在format中为大括号的位置赋值 ''' s = "我的姓名是{}, 年龄是{}".format(name, age) print(s) #格式化的数据来源于容器 info_list = ["小沐1",18] s = "我的姓名是{}, 年龄是{}".format(*info_list) print(s) ''' 赋值的是关键字参数 关键字参数 接受的就是一个字典的格式 需要在站位的时候 {字典中对应的键} ''' s = "我的姓名是{name}, 年龄是{age}".format(name="小明", age=18) print(s) info_dict = {"name":"小强", "age":19} s = "我的姓名是{name}, 年龄是{age}".format(**info_dict) print(s) ''' 站位借助于索引 {索引值} ''' s = "我的姓名是{0}, 年龄是{1}, 时间是{1}".format("小红", 10) print(s) ''' 字符串显示的时候 有些数据需要格式化 小数保留多少位显示 需要使用小数的占位符 :f :.nf n的话表示的是保留的位数 想让数据以二进制格式显示 :b 八进制 :o 十六进制 :x 数值大的情况下 按照千位分割显示 :, ''' s = "我的成绩是{:.2f}".format(67.875) print(s) s = "二进制显示{:b}".format(10) print(s) s = "八进制显示{:o}".format(10) print(s) s = "十六进制显示{:x}".format(10) print(s) s = "数据千位分割显示{:,}".format(123456789) print(s) -------------------------------------------------------------------------------- #8.在字符串中可以使用运算符 ''' 如何判断哪些类型可以使用指定的运算符?? 取查看对应的类型中是否有 这些方法的实现: __add__ =====> + __sub__ =====> - __mul__=====> * __truediv__ ====> / __floordiv__ ====> // __mod__ ====> % __eq__ ====> == __ne__ ====> != __ge__ ====> >= __gt__======> > __le__ =====> <= __lt__ =====> < ''' ''' 在字符串中可以操作的运算符 + ====> 必须是两个字符串类型数据相加 结果生成一个新的字符串 字符串的内容是两个字符串的拼接 * ====> 一个字符串乘以的整型数值 结果生成一个新的字符串 字符串的内容是原有内容重复n次 % ====> 格式化字符串的一种方式 也有一些占位符 %d ----> 整数 %f -----> 小数 %.nf %s -----> 表示其它类型的数据 in 针对于字符串内容比较大小 >= > <= < == != ''' s1 = "abc" s2 = "opq" new_s = s1 + s2 print(new_s, s1, s2) new_s = s1 * 3 print(new_s) #%格式化 ''' 与format是类似 先将要进行格式化的字符串声明完成 使用对应的占位符进行占位 在 % 后 为这些占位符赋值 ''' s = "我的姓名是%s" % "小强" print(s) s = "我的姓名是%s, 年龄是%d 成绩是%.2f" % ("小强", 17, 78.567) print(s) -------------------------------------------------------------------------------- #9.去除掉字符串两端的指定内容 s = "abc你好abcabc" new_s = s.strip("abc") print(new_s) ''' strip([去除的指定的字符串]) 如果没有赋值 去除的是两端的空白字符串 ''' s = " good good \n" new_s = s.strip() print(new_s) #只去除左端 new_s = s.lstrip() print(new_s) #只去除右端 new_s = s.rstrip() print(new_s) -------------------------------------------------------------------------------- s = r"c:\documents\notes\1.听写.MP4" #10.关于判断的方式 #10.1 判断字符串是否以指定内容开头 ====> 从左到右查看子串的内容是否与原串前面的内容是对应的? res = s.startswith(r"c:\documents\notes\1.听写.MP4") print(res) #10.2 判断字符串是否以指定内容结尾 ====> 从右到左查看子串的内容是否与原串前面的内容是对应的? res = s.endswith(r"1.听写.MP4") print(res) s = "10a" #10.3 判断字符串内容是否是纯数字 res = s.isdigit() print(res) s = "10*" #10.4 判断字符串中的内容是否是纯字母 res = s.isalpha() print(res) #10.5 判断字符串中的内容是否是数字或字母 res = s.isalnum() print(res) -------------------------------------------------------------------------------- s = "Hello nice to meet you" #11.转换的方法 #11.1 将字符串中的小写字母转化为大写字母 new_s = s.upper() print(new_s) #11.2 将大写字母转话为小写字母 new_s = s.lower() print(new_s) #11.3 大写转小写 小写转大写 其他符号保持不变 new_s = s.swapcase() print(new_s) s = "hello nIce" #11.4 将字符串中第一个字符转化为大写 其他转化为小写 new_s = s.capitalize() print(new_s) #11.5 将字符串中每个单词的首字母大写 其他小写 # 单词: 在字符串中使用空格隔开的子串 new_s = s.title() print(new_s) #11.6 编码和解码 ''' 生活中的数据 计算集中的数据: 字节数据 编码 ----> 将生活中的数据转化为计算机中的数据 解码 ----> 将计算机中的数据解析成生活中的数据 ''' s = "你好" encode_data = s.encode(encoding="utf-8") print(encode_data) #b'\xe4\xbd\xa0\xe5\xa5\xbd' 使用十六进制表示的 ''' utf-8下1个汉字占3个字节 1个字节是8位二进制数 字符对应的十进制数据 最小的为0 这8位二进制数 可以对应着多少十进制数 2^8 = 256 0000 0000 ----> 0 0111 1111 ----> 2^8-1 1 2 4 8 16 32 64 128 256 256个十进制数 ---> [0, 255] ---> 十六进制[0x00, 0xff] ''' s = "你好啊" encode_data = s.encode(encoding="gbk") print(encode_data) #解码--- 解码方式要与编码方式一致 否则会出现解码错误 decode_str = encode_data.decode(encoding="gbk") print(decode_str) -------------------------------------------------------------------------------- #12. 替换字符串 s = "cat and dog" new_s = s.replace("a", "A") print(new_s) s = "cat and dog" #指定替换的个数 new_s = s.replace("a", "A", 1) print(new_s) -------------------------------------------------------------------------------- #13.以指定拼接符 拼接指定序列中的数据 ''' "拼接符".join(序列) ''' str_list = ["h", "e", "l", "l", "o"] #===> hello res = "*".join(str_list) print(res) str0 = "hello" res = "-".join(str0) print(res) -------------------------------------------------------------------------------- ''' 字符串模块 string ''' import string #1. 所有的空白符号 res = string.whitespace print(res) print("\f") #向上的箭头 #2. 所有小写字母 lower_str = string.ascii_lowercase #3. 所有的大写字母 upper_str = string.ascii_uppercase #4. 所有英文字母 all_case = string.ascii_letters #5.所有数字字符 num_str = string.digits print(lower_str, upper_str, all_case, num_str) -------------------------------------------------------------------------------- #随机数的时候 在字母和数字中随意获取指定个数的字符 import random ch_list = random.sample(string.digits + string.ascii_letters, 5) print(ch_list) #把列表中的数据拼接成一个字符串串 --- 验证码 res = "".join(ch_list) print(res)
#自己获取字符串的长度 #len("abc") def cus_len(itearable): #声明一个计数器 num = 0 #遍历序列 ''' 遍历的时候 需要在序列中获取数据的 如果需要这些数据 那就得设置一个变量接受这些数据 for 变量名 in 序列: pass 如果不需要 可以使用下划线 在变量名处站位 for _ in 序列: pass ''' for _ in itearable: num += 1 return num res = cus_len("abcdefg") print(res) #统计某个字符出现的次数 --- 只统计单个字符 def cus_count_single_ch(src_str, key_ch): ''' 统计指定单个字符在字符串中出现的次数 :param src_str: 指定的字符串 :param key_ch: 要查找的指定字符 :return: 指定字符出现的次数 ''' #计数器 count = 0 #遍历字符串 for ch in src_str: if ch == key_ch: count += 1 return count res = cus_count_single_ch("hello nice look beauty", "e") print(res) ''' 统计某个子串在字符串中出现的次数 特别简单的方法 --- 借助切割 以子串为切割点 ''' def cus_count(src_str, sub_str): sub_list = src_str.split(sub_str) print(sub_list) return len(sub_list) - 1 res = cus_count("good look nood", "oo") print(res) ''' 逻辑思维复杂的: 自己去数 数的话 分为两种情况: 以待找的子串长度 从原串提取出来子串 提取的子串 == 待找的子串 次数 += 1 查找范围更新 ---> 起始位置+待找子串的长度 提取的子串 != 待找的子串 起始位置 += 1 ''' def cus_count_1(src_str, key_str): #计数器 count = 0 # 查找的起始范围 start = 0 #查找: while True: sub_str = src_str[start:start + len(key_str)] if sub_str == key_str: #计数器 +1 count += 1 #查找起始发生变化 start += len(key_str) else: start += 1 #查找的起始值发生变化 if start >= len(src_str): break #如果查找起始范围到原串的最大位置 不用再找了 return count res = cus_count_1("good look nood", "oo") print(res) ''' 方案3: 借助find find("子串", 起始值) 从起始值开始 查找第一次出现的子串索引 如果有的话 返回子串中第一个字符的索引位置 如果没有返回-1 ''' def cus_count_2(src_str, key_str): #计数器 count = 0 #设置起始值 start = 0 #循环查找 while True: index = src_str.find(key_str, start) if index == -1: break else: count += 1 #更改start的起始位置 start = (index + len(key_str)) return count res = cus_count_2("good look nood", "oo") print(res) ''' start = 0 index = s.find("oo", start) index = 1 count += 1 start = index + len(key_str) index = 6 count += 1 start = index + len(key_str) ''' ''' find 查找第一次出现的子串的位置 有的话返回第一个字符的位置 没有的话返回-1 ''' #查找某个字符第一次出现的位置 def find_single(src_str, key_ch): #因为要获取的字符的位置 所以遍历的时候是按照索引遍历的 for i in range(len(src_str)): if src_str[i] == key_ch: return i return -1 res = find_single("hello nice", "m") print(res) #查找某个字符串第一次出现的位置 找到的话返回的第一个字符的索引 否则返回-1 ''' 从头开始提取待找子串长度的子串 提取出来的子串 == 待找的子串 返回start 提取出来的子串 != 待找的子串 start += 1 ''' def cus_find(src_str, key_str): #起始值 start = 0 #进行查找 while True: #按照待找子串的长度提取子串 sub_str = src_str[start:start + len(key_str)] if sub_str == key_str: return start else: start += 1 #从起始位置 + 待查找的子串的长度 已经查过了原串的大小了 if start + len(key_str) > len(src_str): break return -1 res = cus_find("hemllo nicem", "emm") #start = 10 [10: 13) print(res) #将字符串中大写字母转化为小写字母: def cus_lower(src_str): #字符串内容发生变化 起始是新生成了一个字符串 new_str = "" #遍历字符串 for ch in src_str: if "A" <= ch <= "Z": #将其转化为小写 lower_ch = chr(ord(ch) + 32) new_str += lower_ch else: new_str += ch return new_str res = cus_lower("HeLLo") print(res)
32.3 列表数据类型的使用
列表是一个容器 可以存放多个数据, 每个数据都会有自己的编号 这个编号是从0开始的 列表是一个有序的容器 === 存放顺序和显示顺序是一致的 列表的标识是 [] 列表对应的类型名字list
常用方法:
#1. 列表的声明方式 #方式1 使用系统提供的方法 ''' list() list(序列) -- 将其他序列转化为列表 ''' list0 = list() # 生成了一个空列表 ===> [] print(list0) #生成一个列表 列表里面的元素指定序列中的元素 list0 = list("abcd") print(list0) list0 = list((12, 34, 56)) print(list0) #将字典中的键存放于列表中 dict0 = {"name":"小明", "age":18} list0 = list(dict0) print(list0) #获得字典中所有的键 keys = dict0.keys() print(keys) #获取字典中所有的值 values = dict0.values() print(values) #获得字典中所有的键值对 items = dict0.items() print(items) #将字典中的值全部存放于列表中 list0 = list(dict0.values()) print(list0) #将字典中的键值对全部存放于列表中 list0 = list(dict0.items()) print(list0) #将集合中的数据存放于列表中 list0 = list({12, 34, 56}) print(list0) #方式2 使用字面量形式直接赋值 使用中括号的形式直接赋值[] 最常用的方式 list1 = [] print(list1) list1 = [12, 45, 67] print(list1) #2. 可以通过元素索引操作列表中的数据 ''' 索引有两种表现形式 [0, len(list0)-1] [-len(list0), -1] 注意索引范围 ''' #获取列表中的元素 #value = list1[len(list1)] #IndexError: list index out of range value = list1[0] print(value) #更改列表中的元素 list1[1] = 88 print(list1) #3列表中使用的运算符 ''' + 两个列表相加 生成一个新的列表 列表中的元素为两个列表拼接在一起的结果 in * 乘以的一个正整数 生成一个新的列表 列表中的元素为原列表的n倍 >= <= > < == != 与字符串比较类型 将两个列表中的元素一一进行对比 ''' l1 = [12, 34] l2 = [55, 27, 12] new_list = l1 + l2 print(new_list, l1, l2) new_list = l1 * 3 print(new_list, l1) l1 = [12, 34] l2 = [12, 34, 56] res = l1 >= l2 print(res) l1 = [12, 34] l2 = [12, 34] res = l1 == l2 print(res) #4.切片 --- 原则等同于字符串的切片原则 --- 提取子列表 ''' [start:stop[:step]] :step可以省略 默认为1 start 和 stop表示的是索引 不设置值的话默认是从头到尾 设置值的话不包含stop本身 ''' l1 = [12, 56, 71, 23, 54, 38] sub_list = l1[:] print(sub_list) sub_list = l1[:2] print(sub_list) sub_list = l1[2:] print(sub_list) sub_list = l1[2:5] print(sub_list) sub_list = l1[::-1] print(sub_list) #5.列表提供了一个反转的方法 l1.reverse() #这个反转功能没有返回值 修改的是原列表 print(l1) #6.列表中添加元素的操作 -- 操作的都是列表本身 没有返回其他数据 #在末尾追加 l1.append(19) print(l1) #2. 在指定位置插入 l1.insert(0, 29) print(l1) #3. 将其他序列中的元素追加到列表的末尾 合并列表 l1.extend("abc") print(l1) l1.extend([14, 12]) print(l1) #7.移除的方法 #移除指定元素: 第一次出现的元素 l1.remove(12) print(l1) #移除末尾的元素 l1.pop() print(l1) #移除指定位置的元素 l1.pop(1) print(l1) #8.获得列表中指定元素出现的个数 l1 = [12, 34, 56, 12, 71, 12] res = l1.count(12) print(res) #9. 获得指定元素第一次出现的位置 不常用 找不到会报错 # index = l1.index(122) # print(index) #10. 对列表中的元素进行排序 l1 = [12, 34, 71, 29, 56, 44] # l1.sort() # 按照数据的大小 升序排序 # print(l1) #按照数据大小降序排序 # l1.sort(reverse=True) # print(l1) l1 = ["hello", "nice", "family"] #以字符串长度为标准 对列表进行排序 l1.sort(key=len, reverse=True) print(l1) ''' key 接受的是一个函数 默认是None -- 以数据原有大小为标准进行排序 如果不为None 将列表中的数据作用函数 以函数的返回结果为标准 对列表元素进行排序 reverse 默认是False -- 表示升序排序 True --- 降序排序 ''' def cus_sort(src_list): for out in range(1, len(src_list)): for inner in range(out, 0, -1): if src_list[inner] < src_list[inner-1]: src_list[inner], src_list[inner-1] = src_list[inner-1],src_list[inner] list0 = [56, 27, 31, 44, 29] cus_sort(list0) print(list0) ''' 排序影响本身的本质: 给对应的变量传递数据时 赋予的是数据的地址 list0 与 src_list地址是一致的 通过src_list 把地址中对应的数据修改了 list0 通过地址来获取的数据的话 就是发生过修改的 ''' list0 = [56, 27, 31, 44, 29] list1 = list0 list1[0] = 88 print(list0[0]) def cus_sort_1(src_list, reverse=False): #reverse == False 升序 否则为降序 for out in range(1, len(src_list)): for inner in range(out, 0, -1): if reverse == False: if src_list[inner] < src_list[inner - 1]: src_list[inner], src_list[inner - 1] = src_list[inner - 1], src_list[inner] else: if src_list[inner] > src_list[inner - 1]: src_list[inner], src_list[inner - 1] = src_list[inner - 1], src_list[inner] list2 = [29, 41, 38, 55, 42] cus_sort_1(list2, reverse=True) print(list2)
查找列表中的元素 list0 = [34, 71, 29, 30, 46, 77] key_ele = int(input("请输入要查找的元素:")) #设置一个标记 flag = False #默认没有找到 #遍历列表 for ele in list0: if ele == key_ele: print("找到了该元素") flag = True #break # else: # print("没有该元素") if flag == False: print("没有找到该元素") #把顺序查找的方式封装成函数 找到返回数据对应的索引 找不到返回-1 ''' 未知项: 两个未知项 1.进行查找的序列 2.要查找的元素 ''' def search_ele(src_list, key_ele): for i in range(len(src_list)): if src_list[i] == key_ele: return i return -1 res = search_ele([23, 19, 28, 17, 22, 55, 19], 19) print(res) ''' 获得指定元素在列表中的所有位置 如果这个元素在列表中 返回所有的位置 没有的话返回-1 ''' def search_all_ele(src_list, key): #需要一个容器 存放所有的索引 index_list = [] for i in range(0, len(src_list)): if src_list[i] == key: index_list.append(i) # if len(index_list) == 0: # return -1 # else: # return index_list return -1 if len(index_list) == 0 else index_list res = search_all_ele([23, 19, 28, 17, 22, 55, 19], 29) print(res)
听写
使用系统提供的方法: s = "nice to meet you you are very beautiful" 1. 获得字符串的长度 res = len(s) 2. 从字符串中的第一个"o" 开始提取子串 index = s.find("o") sub_s = s[index:] 3. 对字符串以空格为分割符 进行分割 str_list = s.split(" ") 4. 将分割后的数据使用"--"为拼接符拼接在一起 res = "--".join(str_list) 5. 对分割后的数据进行排序 以字符串长度为排序标准 进行降序排序 str_list.sort(key=len, reverse=True) 6. 将s字符串进行反转 res = s[::-1] #[-1:-len(s)-1:-1] 7. 将s字符串的首字母大写 其他字母为小写 res = s.capitalize() 8. 将s字符串中每个单词的首字母大写 res = s.title() 9. 对s字符串以"gbk"形式进行编码 和 解码 编码: 将生活中的数据编译成计算机识别的数据[字节数据] 解码: 将计算机识别的数据[字节数据]转义成生活中的数据 encode_data = s.encode(encoding="gbk") decode_str = encode_data.decode(encoding="gbk") 10.判断字符串的内容是否是纯字母 res = s.isalpha() 11. 判断字符串的内容是否是纯数字 res = s.isdigit() s.isalnum() # 是否是字母或数字
问题 1.break的使用 break 作用于循环语句 跳出当前所在的循环 #设置一个功能: 可以接受任意参数 获得这些数据中的奇数 def get_odd(*values): #values = (12, 13, 17, 28, 15) odd_list = [] for v in values: #v = 12 if v % 2 == 0: #break continue else: odd_list.append(v) return odd_list get_odd(12, 13, 17, 28, 15) 3.遍历序列 list0 = ["nice", "beauty", "family"] max_value = list0[0] for i in list0: if len(i) > len(max_value): max_value = i print(max_value) #索引 for i in range(0, len(list0)): if len(list0[i]) > len(max_value): max_value = list0[i] print(max_value) #遍历序列的时候 如果后面跟随的是序列 前面的变量接受的是序列中的元素值 可不是索引 后面跟随的是range(0, len(list0)) 这个时候才获取的是索引
作业: ''' 3.字符串第一个字符大写 其他小写 4.字符串中每个单词的首字母大写 其余小写 5.去除掉字符串两端的指定内容 思路:从前向后按照内容长度提取子串 与指定内容比较 记录起始位置 一直到不相等位置 提取后面的内容与子串内容比较 记录索引 一致到不相等位置 根据前后索引 利用切片提取子串 ''' #字符串第一个字符大写 其他小写 def cus_capitalize(src_str): #声明一个变量 记录改变之后的字符串 new_str = "" if len(src_str) != 0: #判断第一个字符: if "a" <= src_str[0] <= "z": new_str += chr(ord(src_str[0]) - 32) else: new_str += src_str[0] #遍历第一个之后的 for i in range(1, len(src_str)): if "A" <= src_str[i] <= "Z": new_str += chr(ord(src_str[i]) + 32) else: new_str += src_str[i] return new_str res = cus_capitalize("abC") print(res) def cus_title(src_str): new_str = "" #对字符串进行切割 str_list = src_str.split(" ") #列表中存放的一个个的字符串 print(str_list) #遍历列表 # for i in range(0, len(str_list)): # if i == len(str_list) -1: # new_str += cus_capitalize(str_list[i]) # else: # new_str += cus_capitalize(str_list[i]) + " " #设置一个新的列表 存放转换之后的字符串 new_str_list = [] for ele in str_list: new_ele = cus_capitalize(ele) new_str_list.append(new_ele) new_str = " ".join(new_str_list) return new_str res = cus_title("hello nice") print(res) ''' 5.去除掉字符串两端的指定内容 思路:从前向后按照内容长度提取子串 与指定内容比较 记录起始位置 一直到不相等位置 提取后面的内容与子串内容比较 记录索引 一致到不相等位置 根据前后索引 利用切片提取子串 abcabc1234567abc ''' def cus_strip(src_str, del_str): ''' 去除字符串两端的指定内容 :param src_str: 原生的字符串 :param del_str: 要删除的指定内容 :return: 返回的是去取指定内容之后的字符串 ''' #起始索引 start = 0 #结束索引 end = len(src_str) #从前向后看 while True: sub_str = src_str[start:start + len(del_str)] if sub_str == del_str: start += len(del_str) else: break #从后向前看 while True: end_sub_str = src_str[end - len(del_str):end] if end_sub_str == del_str: end -= len(del_str) else: break return src_str[start:end] res = cus_strip("abcab123456abcabc", "abc") print(res) s = "abcabc1234556abcabc" res = s.startswith("abc") print(res) #指定起始位置 查看从该位置开始是否以指定内容开头 res = s.startswith("abc",4) print(res) res = s.endswith("abc") print(res) #指定起始位置和结束位置 查看从该位置开始是否以指定内容结尾 res = s.endswith("abc",0, 15) print(res) def cus_strip_1(src, del_str): #起始位置 start = 0 #设置一下结束位置 end = len(src) #从前向后看 while True: start_res = src.startswith(del_str, start) if start_res == True: start += len(del_str) else: break #从后向前看 while True: end_res = src.endswith(del_str, 0, end) if end_res == True: end -= len(del_str) else: break return src[start:end] res = cus_strip_1("abcab123456abcabc", "abc") print(res) # list0 = [“nice”, “你好”, “今天天气真好”, “beautiful”, “family", 15, 67, 31] # 1.提取列表中的所有字符串存放于新的列表中 str_list list0 = ["a", "b", "c", 10, 12, "d"] str_list = [] # for ele in list0: # if type(ele) == str: # str_list.append(ele) # print(str_list) for ele in list0: #推荐使用的 判断数据是否是指定类型 if isinstance(ele, str): str_list.append(ele) print(str_list) # list0 = [“nice”, “你好”, “今天天气真好”, “beautiful”, “family", 15, 67, 31] # 1.提取列表中的所有字符串存放于新的列表中 str_list list0 = ["a", "b", "c", 10, 12, "d"] str_list = [] # for ele in list0: # if type(ele) == str: # str_list.append(ele) # print(str_list) for ele in list0: #推荐使用的 判断数据是否是指定类型 if isinstance(ele, str): str_list.append(ele) print(str_list)
32.4 列表中的知识
关于排序的算法
以升序为例:小 ---> 大 冒泡排序: 规则: 遍历列表中的数据[循环]: 从索引为0的位置开始 前后两个元素之间两两进行比较 如果前者 > 后者: 两者交换位置 第一次遍历完成 --- 获得最值 一直遍历到排好序为止 获取列表的最值: list0 = [34, 71, 29, 18, 44] #获得最小值 #1. 声明一个变量 接受比较之后的最小值 假设第一个元素是最小的 min_value = list0[0] #遍历列表 for ele in list0: if ele < min_value: min_value = ele print(min_value) #2.设置最小值对应的索引 假设最小值对应的索引是0 min_index = 0 #根据索引去遍历 for i in range(1, len(list0)): if list0[i] < list0[min_index]: min_index = i print(list0[min_index]) l0 = [56, 27, 31, 44, 29] #外层控制的是遍历的次数 len(l0) - 1 for out in range(1, len(l0)): for inner in range(0, len(l0)-out): if l0[inner] > l0[inner + 1]: l0[inner], l0[inner + 1] = l0[inner + 1], l0[inner] print(l0)
升序排序: 小 ---> 大 选择排序:每次遍历找最值: 降序的话找最大值 升序的话找最小值 规则: 遍历列表 第一次遍历: 假设脚标为0的位置的元素是最小的 将这个位置的元素与之后的每一个元素进行比较 脚标为0的位置的元素 > 后面的元素: 两者交换数据 ----> 脚标为0的位置存放的最小值 第二次遍历: 假设脚标为1的位置的元素是最小的 将这个位置的元素与之后的每一个元素进行比较 脚标为1的位置的元素 > 后面的元素: 两者交换数据 ----> 脚标为1的位置存放的最小值 ... 直到排好序为止 两种方式: #方式1: 直接找最小值元素 list0 = [56, 27, 31, 44, 29] for out in range(0, len(list0)-1): for inner in range(out + 1, len(list0)): if list0[out] > list0[inner]: list0[out], list0[inner] = list0[inner], list0[out] print(list0) #方式2: 找最小值对应的脚标 #根据索引获取最值 for out in range(0, len(list0)-1): #假设固定脚标对应的元素是最小的 min_index = out for inner in range(out + 1, len(list0)): if list0[inner] < list0[min_index]: min_index = inner #这个时候找到的是最小值对应的脚标 最小值对应的元素应该放于固定的位置上 #交换固定脚标与最小值对应的脚标两个位置的数据 list0[out], list0[min_index] = list0[min_index], list0[out] print(list0)
升序: 小 ----> 大 插入排序:-- 与冒泡是反向走的 遍历的列表: 第一次遍历的时候 从脚标为1的元素开始 与前面的元素两两进行比较 第二次遍历的时候 从脚标为2的元素开始 与前面的元素两两进行比较 .... 排好序为止 插入排序 ---- 会达到部分有序的情况 list0 = [56, 27, 31, 44, 29] for out in range(1, len(list0)): for inner in range(out, 0, -1): if list0[inner] < list0[inner-1]: list0[inner], list0[inner-1] = list0[inner-1], list0[inner] else: break print(list0)
列表中提供了排序的方式:
list0 = [56, 27, 31, 44, 29] list0.sort()#升序 list0.sort(reverse = True) #降序 影响的是列表本身 没有生成新的列表
import operator 一. 按字典值排序(默认为升序) x = {1:2, 3:4, 4:3, 2:1, 0:0} 1. sorted_x = sorted(x.iteritems(), key=operator.itemgetter(1)) print sorted_x #[(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)] #如果要降序排序,可以指定reverse=True 2. sorted_x = sorted(x.iteritems(), key=operator.itemgetter(1), reverse=True) print sorted_x #[(3, 4), (4, 3), (1, 2), (2, 1), (0, 0)] 二. 或者直接使用list的reverse方法将sorted_x顺序反转 #sorted_x.reverse() 三. 更为常用的方法是,用lambda表达式 3. sorted_x = sorted(x.iteritems(), key=lambda x : x[1]) print sorted_x #[(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)] 4. sorted_x = sorted(x.iteritems(), key=lambda x : x[1], reverse=True) print sorted_x #[(3, 4), (4, 3), (1, 2), (2, 1), (0, 0)] 四. 包含字典dict的列表list的排序方法与dict的排序类似,如下: x = [{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}] sorted_x = sorted(x, key=operator.itemgetter('name')) print sorted_x #[{'age': 10, 'name': 'Bart'}, {'age': 39, 'name': 'Homer'}] sorted_x = sorted(x, key=operator.itemgetter('name'), reverse=True) print sorted_x #[{'age': 39, 'name': 'Homer'}, {'age': 10, 'name': 'Bart'}] sorted_x = sorted(x, key=lambda x : x['name']) print sorted_x #[{'age': 10, 'name': 'Bart'}, {'age': 39, 'name': 'Homer'}] 5. sorted_x = sorted(x, key=lambda x : x['name'], reverse=True) print sorted_x #[{'age': 39, 'name': 'Homer'}, {'age': 10, 'name': 'Bart'}]
关于查找
顺序查找: 规则: 遍历列表 获取列表中的元素 与待查找的数据进行对比 进而进行查找行为 list0 = [34, 71, 29, 30, 46, 77] key_ele = int(input("请输入要查找的元素:")) #设置一个标记 flag = False #默认没有找到 #遍历列表 for ele in list0: if ele == key_ele: print("找到了该元素") flag = True #break # else: # print("没有该元素") if flag == False: print("没有找到该元素") #把顺序查找的方式封装成函数 找到返回数据对应的索引 找不到返回-1 ''' 未知项: 两个未知项 1.进行查找的序列 2.要查找的元素 ''' def search_ele(src_list, key_ele): for i in range(len(src_list)): if src_list[i] == key_ele: return i return -1 res = search_ele([23, 19, 28, 17, 22, 55, 19], 19) print(res) ''' 获得指定元素在列表中的所有位置 如果这个元素在列表中 返回所有的位置 没有的话返回-1 ''' def search_all_ele(src_list, key): #需要一个容器 存放所有的索引 index_list = [] for i in range(0, len(src_list)): if src_list[i] == key: index_list.append(i) # if len(index_list) == 0: # return -1 # else: # return index_list return -1 if len(index_list) == 0 else index_list res = search_all_ele([23, 19, 28, 17, 22, 55, 19], 29) print(res)
二分法查找: 查找算法 查找前提: 列表必须是有序[升序或者降序]的状态的 以升序为例:小 ---> 大 规则: 利用索引设置一个查找区间[min, max] ===> [0, len(list0)-1] 获取区间中的中间索引位置 mid = (min + max) // 2 将中间索引位置对应的元素 与 待查找的元素进行比较 list0[mid] == key_ele ----> 找到了 list0[mid] > key_ele: 更新查找范围:更新结束索引 max = mid - 1 list0[mid] < key_ele: 更新查找范围:更新开始索引 min = mid + 1 范围更新好了 --- 出现了新的查找范围 更新该范围下的中间索引 mid = (min + max) // 2 什么情况下找不到????? 从查找范围来看 max < min [min, max] --- 区间不合理的情况下 找不到的情况
#只对排好序的列表进行查找 --- 以升序为例 def half_search(src_list, key): #设置查找初始区间 min_index = 0 max_index = len(src_list) - 1 #获得初始区间对应的中间索引 mid_index = (min_index + max_index) // 2 #循环查找: 要查找的元素 与 中间索引对应的元素不相等 while key != src_list[mid_index]: if key > src_list[mid_index]: #更新查找区间 取后面查找 min_index = mid_index + 1 elif key < src_list[mid_index]: #更新区间 去前面找 max_index = mid_index - 1 #上面的两种情况 都更新了区间范围 需要判断区间的合理性 #[0, 1] if max_index >= min_index: #区间是合法的 获取该区间下的中间索引 mid_index = (min_index + max_index) // 2 else: #区间不合法了 结束查找 return -1 #出了循环 代表数据已经找到了 返回对应的位置 return mid_index res = half_search([34, 51, 66, 72, 83], 183) print(res)
二维列表
什么叫做二维列表: 列表中的元素的类型依然是列表类型的 1.如何获得二维列表中 一维列表的元素 接受二维列表的变量名[索引][索引] #列表中的元素的数据类型依然是列表 #声明方式 two_list = [[15, 78],[24, 56]] print(two_list) #或者 list0 = [12, 34, 56] list1 = [77, 22] two_list = [list0, list1] print(two_list) #获取内层列表中的元素 res = two_list[0] print(res) #res也是一个列表 value = res[0] print(value) #上述的两个式子可以合并 value = two_list[0][0] print(value) 2.对二维列表进行遍历 for ele in two_list: print(ele) #接受是二维列表中的内层列表 for e in ele: #想获取内层列表的数据 需要对内层列表进行遍历 print(e)
32.5 元组数据类型
元组也是容器 可以存放多个数据 每个数据都有自己的编号 编号是从0开始的 与列表的区别: 1. 列表长度是可变的 元组时不可变的 2. 列表中元素对应的地址是可变的, 元组中元素对应的地址是不可变的 3. 列表的标识是[], 元组的标识是() 4. 只有一个元素时, 列表中可以在中括号中直接包含元素数据 在元组中必须得在该数据的后面添加逗号 否则解释器会将小括号解释为提高优先级的含义
常用方法: #1. 声明方式 #1.1 使用方法进行声明 ''' tuple() -- 生成的是一个空元祖 tuple(序列) -- 将指定序列转化为元组 将序列中每一个元素存放于元组中 ''' tuple0 = tuple() # ===> () print(tuple0) tuple0 = tuple("abc") print(tuple0) tuple0 = tuple([12, 34]) print(tuple0) tuple0 = tuple({"a":97, "b":98}) print(tuple0) tuple0 = tuple({"a":97, "b":98}.values()) print(tuple0) tuple0 = tuple({"a":97, "b":98}.items()) print(tuple0) tuple0 = tuple({12, 34, 56, 77}) print(tuple0) #1.2 字面量形式的声明 tuple1 = () print(tuple1) #注意只有一个元素的时候 要在元素的后面添加逗号 tuple1 = (10) print(tuple1) print(type(tuple1)) #int tuple1 = (10,) print(tuple1) print(type(tuple1)) #tuple tuple1 = (34, 56, 71, 28, ["a", "b"]) #2.可以通过索引获取元组中的数据 ''' 索引有两种表示方式: [0, len(tuple1)-1] [-len(tuple1), -1] ''' value = tuple1[0] print(value) #3.元组中元素对应的地址是不可变的 但是允许地址中对应的内容发生变化 #tuple1[4] = None # tuple1[4] = None #TypeError: 'tuple' object does not support item assignment tuple1[4][0] = "M" print(tuple1) tuple1 = (13, 45, 71, 28) #4.切片 --- 提取子元组 ''' [start:stop:step] start 和 stop表示索引 可以省略 省略的话 默认是从头到尾 但是两者之间的冒号不允许省略 step 表示是步长 默认是1 步长如果省略的话 前面的冒号可以省略 如果修改了步长 冒号必须有 ''' sub_t = tuple1[:] print(sub_t) sub_t = tuple1[:2] print(sub_t) sub_t = tuple1[1:] print(sub_t) sub_t = tuple1[::-1] print(sub_t) #5. 在元组中能够使用的运算符 ''' +: 合并两个元组 将合并的结果存放于一个新的元组中 in: 成员的判断 * : 乘以的是一个正整数 将圆元组中的数据重复n倍 存放于一个新的元组中 跟列表/字符串比较是一致的 两者以相同索引位置的元素一一进行比较 >= <= > < == != ''' tuple1 = (12, 34) tuple2 = (55, 66) new_tuple = tuple1 + tuple2 print(new_tuple, tuple1, tuple2) new_tuple = tuple1 * 5 print(new_tuple) #6. 常用方法的使用: #6.1 获取指定元素出现的个数 num = new_tuple.count(12) print(num) #6.2 获取某个元素第一次出现的位置 不常用 index = new_tuple.index(12) print(index)
32.6 字典的使用
字典中存放的数据是成对出现的, 存放的是具有映射关系的数据. 注意: 字典是没有编号一说, 字典是根据键查找数据的 字典: 字典的键不允许重复 字典的类型的名字: dict 字典的标识是 {} 字典的使用场景: 如果想显示的数据是成对出现的 ----> 必须使用字典 键值对的格式: key:value
常用的方式:
#1.字典的声明方式 #1.1 使用方法声明 #生成空的字典 dict0 = dict() #===> {} print(dict0) #将序列转化为字典 序列的要求: 该序列必须是二维序列 内层序列中必须有两个元素 # [[12, 34],[34, 56]] two_list = [[12, 34],[34, 56]] for item in two_list: k, v = item print(item) print(k, v) for k, v in two_list: print(k, v) dict0 = dict(two_list) print(dict0) new_dict = {} for k, v in two_list: print(k, v) new_dict[k] = v print(new_dict) #可以接受关键字参数 dict0 = dict(one=1, two=2) print(dict0) #变量的数据可以来源于容器 # a, b = 12, 34 # a, b = [12, 34] #1.2使用字面量形式 - 直接使用{}来完成字典的声明 dict1 = {} #空的字典 print(dict1) dict1 = {"a":97, "b":98, "d":100, "c":99} print(dict1) ----------------------------------------------------------------------------------- #2.字典是根据键来查找值的 #查找方式: 变量名[键] #这种方式有一个弊端 如果键不存在 会报错keyerror 不建议使用这种方式获取值 value = dict1["b"] print(value) # value = dict1["B"] # print(value) #通过这种方式添加键值对 或者 为某个键修改值 #如果键不存在 会添加一个新的键值对 如果存在 会新值覆盖旧值 #格式: 变量名[键] = 值 dict1["a"] = 90 print(dict1) dict1["e"] = 101 print(dict1) #建议使用下列方法根据键获取值 #如果键不存在返回None #变量名.get(键) value = dict1.get("B") print(value) ----------------------------------------------------------------------------------- #合并字典 -- 会将后面的字典的内容合并到前者 dict2 = {"z":122, "y":121, "a":97} dict1.update(dict2) print(dict1) ----------------------------------------------------------------------------------- #3.删除键值对 #变量名.pop(键) dict1.pop("b") print(dict1) #或者 借助del ==delete关键字 del dict1["c"] print(dict1) #del可以删除任意变量 a = 10 print(a) del a #直接将对应的变量在内存中删除 #print(a) list0 = [12, 34, 56] del list0[0] print(list0) ----------------------------------------------------------------------------------- #删除最后一个键值对 dict1.popitem() print(dict1) ----------------------------------------------------------------------------------- #获取字典中所有的键 keys = dict1.keys() print(keys) ----------------------------------------------------------------------------------- #获得字典中所有的值 values = dict1.values() print(values) ----------------------------------------------------------------------------------- #获得所有的键值对 items = dict1.items() print(items) ----------------------------------------------------------------------------------- #字典的遍历 #直接遍历字典 获取的是字典中的键 for ele in dict1: print(ele) ----------------------------------------------------------------------------------- for ele in dict1.keys(): print(ele) #遍历所有的值 for v in dict1.values(): print(v) #获取键值对 -- 只能遍历items for item in dict1.items(): print(item) k, v = item print("{}:{}".format(k, v)) for k, v in dict1.items(): print("{}:{}".format(k, v)) ----------------------------------------------------------------------------------- #清空字典 dict1.clear() print(dict1) ----------------------------------------------------------------------------------- #清空列表 [12, 34].clear() -----------------------------------------------------------------------------------
案例: 统计字符串中每个字符出现的次数 思路: 需要一个字典的容器存放最终显示的数据 键:值 字符当做键 次数是值 遍历字符串 获取每一个字符 字符第一次出现 次数是1 之后再出现 在原来的基础上+1 问题: 如何判断时候是第一次出现??????? 判断字典中是否有对应的字符为键 ---> 键是否被字典包含 ---> 键是否是字典的成员 in s = "hellohighgoodnicelike" #1.声明一个字典 count_dict = {} #2.遍历字符串 for ch in s: #判断这个字符串是否已经在字典中作为键 if ch not in count_dict: count_dict[ch] = 1 else: count_dict[ch] += 1 print(count_dict) #获得出现次数最高的字符 #1. 需要获得value中的最大值 max_count = max(count_dict.values()) print(max_count) #2. 声明一个容器 存放满足最大值的键 key_list = [] #3.遍历字典的键值对 for k, v in count_dict.items(): if v == max_count: key_list.append(k) print(key_list)
练习: 字符串word = "good good study day day up" a. 获取上述字符串中每个单词出现的次数 b. 获得长度最长的单词 word = "good good study day day up" word_list = word.split(" ") print(word_list) word_dict = {} for w in word_list: if w not in word_dict: word_dict[w] = 1 else: word_dict[w] += 1 print(word_dict) #根据长度获得列表中的最值 max_len = max(word_list, key=len) print(max_len)
32.7 集合的使用
集合也是一个容器, 容器内的数据是不会重复, 无序的[存放顺序与显示顺序不一致] 集合也没有索引一说 集合的作用: 去重 将重复的数据只保留1个 ===> 去重之后数据的顺序可能与原来不一致 集合的类型名字为set help(set)=====>查看set的方法
常用方法:
#1. 声明方式 #1.1使用方法 set0 = set() #生成的是一个空集合 空集合的表示方式只有一种: set() print(set0) #将其他序列转化为集合 set0 = set("abcdefa") print(set0) set0 = set((14, 51,27)) print(set0) set0 = set([99, 27, 38, 27]) print(set0) data = {} #====> 表示的是空的字典 #1.2 字面量 set1 = {12, 34, 56,71} print(set1) #2. 运算符 ''' & 求两个集合的交集 并把数据存放于一个新的集合中 | 求两个集合的并集 并把数据存放于一个新的集合中 ^ 求两个集合的非交集 并把数据存放于一个新的集合中 - 在前者集合中去除掉与后者交集的部分 >= > <= < == != ''' set1 = {12, 34, 56} set2 = {34, 28, 19} new_set = set1 & set2 print(new_set, set1, set2) new_set = set1 | set2 print(new_set, set1, set2) new_set = set1 ^ set2 print(new_set, set1, set2) new_set = set1 - set2 print(new_set, set1, set2) set1 = {23, 18, 19, 28, 71} #3.在集合中添加元素 set1.add(99) print(set1) #4.在集合中移除元素 #4.1 清空 # set1.clear() # print(set1) #4.2 移除元素 如果该元素存在 移除 不存在没有任何影响 set1.discard(189) print(set1) #4.3 remove ---> 如果不存在会报错 # set1.remove(189) # print(set1) #4.4 pop 移除的任意的一个 会把删除的元素返回 如果是一个空集合 会报错 value = set1.pop() print(set1, value) value = set1.pop() print(set1, value) set1 = {12, 34, 56} set2 = {34, 56, 71} #5.其他方法的使用 #求的是交集 #生成了一个新的集合 存放交集 new_set = set1.intersection(set2) print(new_set, set1, set2) #求的是交集 没有生成新的集合 而是直接影响了前者 # set1.intersection_update(set2) # print(set1, set2) #求并集 new_set = set1.union(set2) print(new_set, set1, set2) # set1.update(set2) # print( set1, set2) #求非交集^ new_set = set1.symmetric_difference(set2) print(new_set, set1, set2) # set1.symmetric_difference_update(set2) # print(set1, set2) #在前者中去除掉与后者的交集 - new_set = set1.difference(set2) print(new_set, set1, set2) # # set1.difference_update(set2) # print(set1, set2) #判断的方式 #1. 判断两个集合是否没有交集 res = set1.isdisjoint(set2) print(res) #2. 判断前者是否是是后者的子集 res = set1.issubset(set2) print(res) #3. 判断后者是否是前者的子集 res = set1.issuperset(set2) print(res)
32.8 集合和字典无序的本质
本质: 源于底层的数据结构 集合的底层数据结构是哈希表 哈希表的组成是由数组和链表组成的 数组的使用: 数组是一个定长的 但是允许数据发生改变的容器 也是有索引定位数据 链表: 由节点组成的 分为单向链表和双向链表 单向链表: 节点是由两部分组成的:存储的数据 + 下一个节点的地址 双向链表: 节点由三部分组成: 上一个节点的地址 + 存储的数据 + 下一个节点的地址 哈希表: 数组和链表组成的 在哈希表中存放数据: 将数据经过哈希函数运算, 生成一个与数组中对应的索引, 根据这个索引定位到数组中的位置, 在该位置处创建一个链表节点,包含要存放的数据 再次放数据的时候, 将该数据经过哈希函数的运算 生成在数组中对应的索引 根据这个索引定位到数组中的位置, 如果这个位置有数据, 新值覆盖旧值的情况, 如果没有数据, 就在此处生成一个链表节点 存放数据
哈希表的数据结构与数组这种数据结构的优缺点: 字典/集合 与 列表的优缺点: 从内存角度分析 字典/集合比列表属于浪费内存 因为列表存放数据 从索引0开始依次存放数据 但是字典/集合 是根据函数计算出来的索引 可能会造成索引跳跃站位的情况 导致某些索引位置处没有数据 但是却占用者内存 从查找效率的角度分析[真对于大量数据] 列表的查询效率要比字典/集合慢 因为列表查询数据的话 需要从头到尾遍历 进行比较判断 如果数据靠后的话 查找会很不便 字典是根据键查寻对应的数据 直接将键经过函数运算出来索引 直接定位到指定索引对应的数据
33. 列表生成式和字典生成式*******
列表生成式/字典生成式 可以理解成对列表或者字典筛选的简化方式 可以快速的生成列表和字典
列表生成式的格式: 列表的标识是[] [要存入列表中的数据 数据的来源 [对数据的筛选]] ====> [对数据的筛选] 可能有 可能没有 看需求 案例: 生成一个存放1-100的数据的列表
#生成一个存放1-100的数据的列表 list0 = [] for i in range(1, 101): list0.append(i) print(list0) # list0 = [1, 2, 3, 4..10] # list0 = list(range(1, 101)) # print(list0) #列表生成式 -- 数据根据for循环来的 list0 = [i for i in range(1, 101)] print(list0) str_list = ["hello", "nice", "10", "20", "good"] new_list = [] for ele in str_list: if ele.isalpha(): new_list.append(ele) print(new_list) new_list = [ele for ele in str_list if ele.isalpha()] print(new_list) #列表生成式 ''' 1. 生成1-10之间的偶数 2. list0 = [12, 34, 56, True, "nice", "like", 3.14] 提取整数类型的数据存放于列表中 3. list0 = [" ", " good_study\n", "\n\t", " \n", " \t", "\tnice"] 提取列表中的非空白字符序列 字符串的strip 什么都不传 去除的字符串两端的空白序列 字符串的split split如果什么都不传 默认以空白字符序列来进行分割 分割之后结果中的空字符串会被移除 ''' #1. new_list = [ele for ele in range(1, 11) if ele % 2 == 0] print(new_list) #2. list0 = [12, 34, 56, True, "nice", "like", 3.14] new_list = [ele for ele in list0 if type(ele) == int] print(new_list) new_list = [ele for ele in list0 if isinstance(ele, int) and not isinstance(ele, bool)] print(new_list) #3. list0 = [" ", " good_study\n", "\n\t", " \n", " \t", "\tnice"] new_list = [ele for ele in list0 if ele.strip() != ""] new_list = [ele for ele in list0 if len(ele.strip()) != 0] new_list = [ele for ele in list0 if ele.split() != []] new_list = [ele for ele in list0 if len(ele.split()) != 0] print(new_list) print(" ".strip(), "v", sep="") print(" ".split())
字典生成式: 字典的标识是{} 字典生成式格式 {键值对 键值对来源 [对键值对的筛选]} [对键值对的筛选] --- 可有可无 按照需求设定 案例: count_dict = {"a":7, "h":3, "m":9, "k":2} ---> 提取字典中次数大于5的键值对 存放于新的字典中
''' count_dict = {"a":7, "h":3, "m":9, "k":2} ---> 提取字典中次数大于5的键值对 存放于新的字典中 ''' count_dict = {"a":7, "h":3, "m":9, "k":2} new_dict = {} for k, v in count_dict.items(): if v >= 5: new_dict[k] = v print(new_dict) #字典生成式 new_dict = {k:v for k, v in count_dict.items() if v >= 5} print(new_dict) ''' 1. 字典: score_dict = {"政治":77, "英语":57, "语文":82, "历史":62} 提取成绩大于等于60的成绩存放于新的字典中 2. word = "hello nice to meet you nice to meet you too" 获得每个单词出现的次数 存放于字典中 将单词长度大于3的键值对 存放于新的字典中 ''' #1. score_dict = {"政治":77, "英语":57, "语文":82, "历史":62} new_dict = {k:v for k,v in score_dict.items() if v >= 60} print(new_dict) #2. word = "hello nice to meet you nice to meet you too" list1 = word.split() word_dict = {} for i in list1: if i not in word_dict: word_dict[i] = 1 else: word_dict[i] += 1 print(word_dict) new_dict = {k:v for k, v in word_dict.items() if len(k) > 3} print(new_dict)
34. 深浅拷贝
地址对应的内容不可以发生变化的数据 是没有拷贝一说的 即使使用拷贝方式 生成的结果使用还是原来的地址 例如数值类型 字符串类型 拷贝需要导入模块 copy copy.copy(数据) ##浅拷贝: 生成一个新的地址 来存放最外层数据的内容 内层数据对应的地址还是使用的原来的 copy.deepcopy(数据) ##深拷贝: 数据一致 但是内外对应的地址不一样
#地址对应的内容不可以发生变化的数据 是没有拷贝一说的 即使使用拷贝方式 生成的结果使用还是原来的地址 #例如数值类型 字符串类型 import copy # a = 10 # print("原数据地址:",id(a)) # #进行浅拷贝 # b = copy.copy(a) # print("浅拷贝数据对应的地址:",id(b)) # #进行深拷贝 # c = copy.deepcopy(a) # print("深拷贝数据对应的地址:",id(c)) ''' 原数据地址: 1916038448 浅拷贝数据对应的地址: 1916038448 深拷贝数据对应的地址: 1916038448 ''' # a = "hello" # print("原数据地址:",id(a)) # #进行浅拷贝 # b = copy.copy(a) # print("浅拷贝数据对应的地址:",id(b)) # #进行深拷贝 # c = copy.deepcopy(a) # print("深拷贝数据对应的地址:",id(c)) ''' 原数据地址: 2687755858192 浅拷贝数据对应的地址: 2687755858192 深拷贝数据对应的地址: 2687755858192 '''
####元素地址对应内容可变的数据 进行深浅拷贝 ''' 地址对应的内容数据是可以发生变化的 可以进行深浅拷贝 例如列表中的数据是可以发生变化的 如果内层数据对应的地址是不能发生变化的 深浅拷贝的结果对于内层数据而言是一致的 ''' # list0 = ["a", "b", "c"] # print("原数据的地址:", id(list0)) # print("内层数据的地址:", id(list0[0])) # #进行浅拷贝 # list1 = copy.copy(list0) # print(list1) # print("浅拷贝生成的地址:", id(list1)) # print("浅拷贝内层数据的地址:", id(list1[0])) # # #进行深拷贝 # list2 = copy.deepcopy(list0) # print(list2) # print("深拷贝生成的地址:", id(list2)) # print("深拷贝内层数据的地址:", id(list2[0])) # list0 = ["a", "b", "c"] # list1 = ["hello", 12, list0] # print("原数据对应的地址:", id(list1)) # print("内层数据地址对应的内容可以发生变化的数据的地址:", id(list1[2])) # # #浅拷贝 # list2 = copy.copy(list1) # print("浅拷贝外层数据对应的地址:", id(list2)) # print("浅拷贝内层数据地址对应的内容可以发生变化的数据的地址:", id(list2[2])) # # #深拷贝 # list3 = copy.deepcopy(list1) # print("深拷贝外层数据对应的地址:", id(list3)) # print("深拷贝内层数据地址对应的内容可以发生变化的数据的地址:", id(list3[2]))
特殊的数据类型: 元组 元组的特殊性: 元组中元素对应的地址是不可变的 #特殊的数据是元组 ''' 元组中元素的地址是不允许发生变化的 ''' # tuple0 = (12, 34) # tuple0[1] = 88 #TypeError: 'tuple' object does not support item assignment tuple0 = (12, 34, ["a", "b"]) #tuple0[2] = [55, 66] #TypeError: 'tuple' object does not support item assignment tuple0[2][0] = "A" #元组中元素的地址没有发生变化 但是该地址对应的内容发生变化 这个是可以的 print(tuple0)
#####元组的拷贝: ''' 拷贝中的元组 如果元组中元素地址对应的内容是不可变的 元组没有深浅拷贝一说 使用的都是原数据的地址 如果元组中元素地址对应的内容是可变的 只有深拷贝一说 ''' # tuple1 = (12, "hello") # print("原数据的地址:", id(tuple1)) # # #浅拷贝 # tuple2 = copy.copy(tuple1) # print("浅拷贝的地址:", id(tuple2)) # # #深拷贝 # tuple3 = copy.deepcopy(tuple1) # print("浅拷贝的地址:", id(tuple3)) tuple1 = (12, "hello", [34, 21]) print("原数据的地址:", id(tuple1)) print("内层地址对应内容可变数据的地址:", id(tuple1[2])) #浅拷贝 tuple2 = copy.copy(tuple1) print("浅拷贝的地址:", id(tuple2)) print("浅拷贝内层地址对应内容可变数据的地址:", id(tuple2[2])) #深拷贝 tuple3 = copy.deepcopy(tuple1) print("浅拷贝的地址:", id(tuple3)) print("深拷贝内层地址对应内容可变数据的地址:", id(tuple3[2]))
总结: 1. 没有拷贝一说的 数值类型 字符串类型 元组中元素的地址对应的内容是不可变的时候 2.没有浅拷贝 只有深拷贝一说 元组中元素的地址对应的内容是可变的时候 3. 具有深浅拷贝的 列表 字典 集合 以及之后自定以的数据类型 浅拷贝: 将数据拷贝一份 生成一个新的外层数据的地址 存放拷贝出来的数据 深拷贝: 将数据拷贝一份 内外数据对应的地址都生成一份新的存放拷贝出来的数据
35. 生成器
生成器的类型 generator 针对于列表生成式的弊端产生的 列表生成式快速的生成一批 数据, 这批数据会立即存放于内存中, 但是使用的使用前面一部分的数据, 对于后面的数据而言数据过度占用内存, 可以使用生成器去生成数据 生成器也可以生成一批数据, 这批数据不会立即存放于内存中 当取出来使用的时候才会在内存中存放对应的数据 生成器中数据一旦取出 生成器中就不存在该数据了 再取的话取的是数据的下一个 在生成器中取数据的方式是通过next(生成器)获取数据 这种方式如果生成器中没有数据了 再取的会报错 设计生成器的方式: 1. 将列表生成式的[] 改为() (数据 数据的来源 [对数据的筛选]) 2. 将函数的定义中 return改为yield def 函数名(): 数据来源 yield 数据 #返回数据
ge = (ele for ele in range(1, 11) if ele % 2 == 0) print(ge) #生成器中存放这数据 -- 也是一个容器 # for i in ge: # print(i) #通常情况下在生成器中获取数据的方式 value = next(ge) print(value) value = next(ge) print(value) value = next(ge) print(value) value = next(ge) print(value) value = next(ge) print(value) print("---------------------") # value = next(ge) # print(value) #StopIteration def get_value(): for i in range(1, 11): if i % 2 == 0: yield i #把数据在生成器中去除 当使用next()方式获取数据的时候 才会调用生成器的内部 print("{}数据已经取出".format(i)) #当下一次next的时候 才会来指定者行代码 ge1 = get_value() print(ge1) value = next(ge1) print(value) value = next(ge1) print(value)
36. 迭代器
只是序列的另外一种遍历方式 遍历的话 for in遍历就可以了 另外一种遍历方式是通过next(序列)来从序列中一个一个的获取数据 能使用next方法迭代数据的只有迭代器类型的才可以 迭代器类型存放于collections下 Iterable --- 验证指定的数据是否是可进行遍历的 Iterator -- 迭代器类型
from collections import Iterable, Iterator print(isinstance(10, Iterable)) print(isinstance("10", Iterable)) print(isinstance(("10",), Iterable)) print(isinstance(["10"], Iterable)) #可不可以通过迭代器进行遍历 print(isinstance(["10"], Iterator)) print(isinstance("10", Iterator)) print(isinstance(("10",), Iterator)) #False 不是迭代器类型 就不可以使用next进行遍历 #如何让数据可以使用迭代器进行遍历呢?? #将指定序列转化为迭代器类型 it = iter("10") value = next(it) print(value) ''' 如果想使用 迭代器对字符串 元组 列表 字典 集合进行遍历 需要将其转化为迭代器类型 it = iter(数据) it就是指定数据对应的迭代器类型 就可以使用next进行遍历 '''
37. 包和程序入口的设定
包: 相当于计算机中的文件夹 常识: 在同一个目录下 不允许存在同名的两个文件 作用: 1.对python文件进行分类管理 2.对python文件提供多级命名空间 m a.py n a.py 创建包: 选中创建包的位置 右键---> new ---> python package ----> 起一个包名 包名的命名规范: 符合标识符规范 英文单词是小写的 单词之间使用下划线隔开 计算中目录的分割是使用\来进行分割的 在程序中包之间的分割是用.来进行分割的 创建出来的是一个包的话 包会自带一个__init__.py的文件 --- 标记这个目录时程序中的包 而非一个普通的文件夹 创建出来包之后 包和包之间的python文件是可以互相访问的 普通文件夹下python文件不可以互相访问 访问方式就是倒模块方式 有了包之后倒模块的方式要发生变化: import 一级包名.二级包名...n级包名.模块名 使用模块下的内容: 一级包名.二级包名...n级包名.模块名.内容的名字 from 一级包名.二级包名...n级包名.模块名 import 具体的内容名字, 内容名字1 from 一级包名.二级包名...n级包名.模块名 import * *默认是导入该模块下所有内容 但是如果模块下有__all__列表的生成 只能导入该列表下指定的内容 起别名 as import 一级包名.二级包名...n级包名.模块名 as 别名 使用模块内容时候 使用别名进行调用 而且只能使用别名调用 # import pack1.sub_pack.tool #as 就是起别名 import pack1.sub_pack.tool as pst # # res = pack1.sub_pack.tool.add(12, 34) # print(res) res = pst.add(12, 34) print(res) 同一个包下面的两个python文件互相访问 导入模块的时候 可以直接使用模块名导入 如果提示错误 这个错误可以忽略 如果看不了这个错误 导入包名.模块名
程序入口的设定: 在程序中标记出来 起始指定文件 --- 告知其他人程序入口是哪个文件 如何标记: 在起始文件中加入判断语 if __name__ == "__main__": 程序入口中的内容 其实每个py文件中都有一个 __name__ 这个字段 如果起始文件 这个字段的值为 "__main__" 其他py文件 __name__ 的值为对应的py文件名
模块导入: 第一次进行模块导入时 解释器会针对于这个模块生成一个对应的缓存文件.pyc文件 之后再导入的时候直接使用.pyc文件中的数据 模块时天然的单例 单个实例 只要我导入一次 之后不管再怎么进行导入 使用都是原来生成的那一个内容
38. 浅拷贝
对于列表和字典的数据类型中提供了浅拷贝的方式 列表数据.copy() ===> copy.copy(列表数据) 字典数据.copy() ====> copy.copy(字典数据)
39. 高阶函数
39.1 map函数
help(map) ''' | map(func, *iterables) --> map object 第一个参数 接受的是一个函数 函数的作用是对应序列中的中据进行指定操作的转化 函数类似于排序是key接受的函数 函数有一个参数 函数的返回值是 按照需求对参数转化的结果 注意: 参数默认接受的数据就是序列中的每一个元素了 第二个参数: 序列 ''' str0 = "abcdefg" #将字符串中的每个字符转化为大写字母 map_obj = map(lambda ele: ele.upper(), str0) print(map_obj) #相当于把序列中的内容取出了 取出了容器中就不存在了 # for ch in map_obj: # print(ch) new_str = "".join(map_obj) print(new_str) #字符串的结果 是拼接出来的 能不能使用str(数据)进行转换 ===> 不可以 a = 10 print(a) print(str(a), type(str(a))) # list0 = ["10", "20", "30", "40"] # map_obj = map(int, list0) # new_list = list(map_obj) # print(new_list) print(str(map_obj), type(str(map_obj))) ''' str(变量名) ---> 将变量名对应的数据转化为字符串类型 a = 10 print(a) print(str(a), type(str(a))) str(a) ---> a对应的10转化为字符串 print(str(map_obj), type(str(map_obj))) map_obj --> 变量名 str(map_obj) ----> map_obj对应的数据转化 为字符串 map_obj对应的值:<map object at 0x0000022B61219208> str(map_obj) ===> "<map object at 0x0000022B61219208>" ''' # list1 = [12, 34] # res = str(list1) # print(res) #"[12, 34]" ''' 练习: 1. list0 = [2, 4, 6, 8, 10] ---> 将列表中的每一个数据 求平方 存于新的列表中 2. list0 = ["12", "hello", "nice", "34"] ----> 将列表中的数据 进行转化 列表中的字符串只有两种格式: 纯字母 和 纯数字 如果字符串内容为纯字母 保留原字符串 否则字符串内容为纯数字 转化为整型 map(函数, 序列) ''' #1. list0 = [2, 4, 6, 8, 10] new_list = list(map(lambda x:x**2, list0)) print(new_list) #2. list0 = ["12", "hello", "nice", "34"] def x(s): if s.isalpha(): return s else: return int(s) new_list = list(map(x, list0)) print(new_list) #map的另外一种使用方式 ''' map接受序列的时候 可以接受多个序列 接受多个序列一般进行的操作 是按照设置的格式对多个序列中的内容进行重组 对序列进行重组 函数的设置的形参: 有几个序列 设置几个形参 形参接受元素的顺序 与 设置序列的顺序是一致的 形参接受的数据 -- 默认接受的就是对应序列中的每一个元素 ''' i1 = range(1, 11) i2 = "abcdefghij" #操作:i1中的1-i2中的a def new_ite(a, b): return (b, a) map_obj = map(new_ite,i1, i2) # for item in map_obj: # print(item) # list0 = list(map_obj) # print(list0) dict0 = dict(map_obj) print(dict0)
39.2 zip函数
zip函数的使用类似于map的第二种使用方式 将多个序列中的数据进行重组
help(zip) ''' zip(iter1 [,iter2 [...]]) --> zip object 参数就是序列 ----> 将指定序列中的数据 根据对应的位置依次取出 重组成新的序列 组合的时候 最后新的序列的个数 由序列元素少的决定的 ''' tuple0 = (12, 34, 56) list0 = [15, 23, 71, 89] zip_obj = zip(tuple0, list0) print(zip_obj) # for item in zip_obj: # print(item) dict0 = dict(zip_obj) print(dict0) #将字典的键和值颠倒 dict0 = {"a":97, "b":98, "c":99} new_dict = {v:k for k, v in dict0.items()} print(new_dict) new_dict = dict( zip(dict0.values(), dict0.keys())) print(new_dict)
39.3 filter函数
对序列进行筛选的 接受一个函数 函数有一个形参: 默认接受的就是序列中的每一个元素 函数的返回值是bool类型的 True 表示保留该数据 False 表示去除该数据
help(filter) ''' filter(function, iterable) ---> filter 第一个参数是函数 函数有一个形参 --- 默认已经接受的是序列中的每一个元素 函数有返回值 bool类型的 True为保留 False 为去除 第二个参数 要进行筛选的序列 ''' s = "abcdefg123456*!@#" #去除掉字符串中的非字母和非数字的字符 ===> 只保留字母或数字 new_str = "" for ch in s: if ch.isdigit() or ch.isalpha(): new_str += ch print(new_str) filter_obj = filter(lambda ch : ch.isalpha() or ch.isdigit(), s) print(filter_obj) # for i in filter_obj: # print(i) new_str = "".join(filter_obj) print(new_str) '''' 1. list0 = [" ", "good", "\nlike", "\t\r", "book\t"] 保留列表中非空白字符序列 2. dict0 = {"政治":78, "历史":32, "数学":99} 保留字典中成绩>=60的键值对 ''' #1. list0 = [" ", "good", "\nlike", "\t\r", "book\t"] new_list = list(filter(lambda ele: ele.strip() != "", list0)) print(new_list) #2. dict0 = {"政治":78, "历史":32, "数学":99} new_dict = {k:v for k, v in dict0.items() if v >= 60} print(new_dict) for item in dict0.items(): print(item) # 在dict.items()序列中 每一个元素是一个小元组 元组中有两个数据 第一个是键 第二个是值 #[(),(),()] new_dict = dict(filter(lambda item:item[1]>=60, dict0.items())) print(new_dict)
39.4 reduce函数
需要先导入模块functools from functools import reduce 函数的功能是进行按照要求进行累计的效果 两个参数: 函数 --- 需要接受两个形参 第一次接受的是 序列中的前两个数据 根据功能计算出结果 第二次之后: 将结果和序列中下一个元素传入函数中 取计算结果 序列: 要进行累计的序列
from functools import reduce help(reduce) ''' reduce(function, sequence) -> value ''' s = "123456" # ====> 对字符串的数值进行累加 def add(x, y): return int(x) + int(y) res = reduce(add, s) print(res)
39.5 sorted函数
函数是对序列进行排序的 sorted(指定进行排序的列表, key=进行排序是数据的标准,reverse=升序/降序) 这个排序方式 会新生成一个列表 对原来的列表没有影响 列表类型中自带的排序方式: 要排序的列表.sort(key, reverse) ====> 影响的是原列表
list0 = ["hello", "like", "milk", "good"] #用原生的列表中的方法进行数据大小的升序排序 # list0.sort() # print(list0) #降序 # list0.sort(reverse=True) # print(list0) #修改排序是数据比较的标准 # list0.sort(key=len) # print(list0) #sorted new_list = sorted(list0, key=len) print(list0) #不会影响原列表 print(new_list)