Python入门 – 学完课程之后做的笔记(2022.10.15)
【花了2万多买的Python教程全套,现在分享给大家,入门到精通(Python全栈开发教程)】 https://www.bilibili.com/video/BV1wD4y1o7AS?p=22&share_source=copy_web&vd_source=3429044f238c104ecc668f383c49499c
输出函数print()
-
输入内容
# 1. 输出数字 print(3.1415); # 2. 输出字符串,三种引号都可以代表字符串 print('hello, python'); print("hello, world"); print("""hello, print""") # 3. 输出含有运算符的表达式,会计算后输出计算结果 print(1 + 1); # 4. 将数据输出到文件中 # 注意,1. open()的第一个参数是 文件夹名 + 文件名,其中文件夹名必须存在,否则报错 # 2. open()的第二个参数: a+ 的意思是 如果文件不存在就新建文件,存在则在该文件的末尾继续追加内容 # 扩展:打开文件时,可指定 读取模式('r')、写入模式('w')、附加模式('a')或者能读取和写入文件的模式('r+')。 # 如果省略了模式实参,Python将以默认的只读模式打开文件 fp = open("D:/pythonTemp/test.txt", "a+"); print("hello, file", file = fp); fp.close(); # 5. 输出多句话不换行 print("你好!", "换行了吗?", "没换行吧", "确实没换行");
-
转义字符和原字符
# \n : 换行 print('hello,\nworld'); # \t : 制表符 # 注意,下面两个\t产生的空格数量并不相同 # 原因是:\t 的原理是将字符串每四个字符一组,\t的位置之前的一组如果不满四个字符,则用空格填补成四个字符, # 如第一个print(),hell 是第一组,第二组只有 “o,”两个字符,所以\t的效果是填补两个空格 # 而第二个print(),在 \t 前的一组已经满了,所以\t产生了四个空格,即一组 print('hello,\tworld'); # hell-o,__-worl-d print('hello,oo\t,world'); # hell-o,oo-____-,wor-ld # \r : 覆盖前面的字符 # \r后面的 world 覆盖了\r前面的 helloooo, print('helloooo, \rworld'); # 输出:world # \b : 退格,只退一格 print('hello,\bworld'); # 输出:helloworld # \ 只是转义,无特殊功能 print('http:\\\\www.baidu.com'); print('He say: \'hello, everyone.\''); # 原字符,不希望字符串中的转义字符起作用,就使用原字符, # 使用方法:在字符串的前面加上 r 或 R # 注意:最后一个字符不能是 \ print(r'hello, \rworld'); # 最后面有偶数个 \ 不会报错 print(R'hello, world\\');
变量
-
保留字
# 1.保留字 # 通过以下代码,可以查看python的保留字列表 import keyword print(keyword.kwlist)
-
变量命名规则
- 字母、数字、下划线_
- 不能以数字开头
- 不能使用保留字
- 严格区分大小写
-
变量由三部分组成
-
标识:表示对象所存储的内存地址,使用内置函数 id(obj) 来获取
-
类型: 表示对象的数据类型,使用内置函数 type(obj) 来获取
-
值:表示对象所存储的具体数据
# 2. 变量的组成 name = "zhangsan" print(id(name)) # 1870083052912 print(type(name)) # <class 'str'> print(name) # zhangsan
-
数据类型
-
常用的数据类型
- 整数类型: int
- 浮点数类型:float
- 布尔类型:bool (注意,不是boolean)
- 字符串类型:str (不是string)
-
整数类型
# 1. 整数类型 # 可以表示正整数,负整数,0 # int age = 19 这句代码会报语法错误,不能这样定义变量 age = 19 print(age) # 整数可以表示为二进制、十进制、八进制、十六进制 # 输出时自动转成了十进制 print('十进制', 18) print('二进制', 0b1011001) # 二进制以 0b 开头,输出:89 print('八进制', 0o176) # 八进制以 0o 开头,输出:126 print('十六进制', 0x1EAF) # 十六进制以 0x开头,输出:7855
-
浮点数类型
# 2. 浮点数类型 # 浮点数由整数部分和小数部分组成 pi = 3.14159262 print(pi) # 浮点数存储不精确性 # 浮点数进行计算时,可能会出现小数位数不确定的情况 print(1.1 + 2.2) # 输出:3.3000000000000003 print(1.1 + 2.1) # 输出:3.2 # 解决方案:导入模块decimal from decimal import Decimal print(Decimal('1.1') + Decimal('2.2')) # 输出:3.3
-
布尔类型
# 3. 布尔类型 # 用来表示真或假 print(type(True)) # 输出:<class 'bool'> # 布尔值可以转化为整数,True -> 1, False -> 0 print(True + 1) # 输出:2 print(False + 1) # 输出:1
-
字符串类型
# 4. 字符串类型 # 字符串是不可变的字符序列 name = "zhangsan" print(id(name)) # 输出:2865920795248 username = "zhangsan" print(id(username)) # 输出:2865920795248 # 可以使用单引号,双引号,三引号来定义字符串 # 三引号定义的字符串可以分布在连续的多行 print('hello, python') # 不可换行 print("hello, python") # 不可换行 print("""hello, python""") # 相当于 print("hello, \npython")
-
类型转换
-
str()
# 1. int -> str age = 19 # print("我今年" + age + "岁") # 报错:TypeError: can only concatenate str (not "int") to str print("我今年" + str(age) + "岁") # 输出成功 # 2. float -> str print(str(3.14), type(str(3.14))) # 输出:3.14 <class 'str'> # 3. bool -> str print(str(True), type(str(True))) # 输出:True <class 'str'>
-
int()
# 整型字符串 -> int num = "123" print(int(num), type(int(num))) # 输出:123 <class 'int'> # 只有整型字符串可以通过int()转换成整型 # bool字符串无法转换成整型 print(int("True"), type(int("True"))) # invalid literal for int() with base 10: 'True' # 浮点数字符串无法转换成整型 f = '3.14' print(int(f), type(int(f))) # invalid literal for int() with base 10: '3.14' # 非数字型字符串无法转换成整型 print(int("hello"), type(int("hello"))) # invalid literal for int() with base 10: 'hello' # float -> int # 截取整数部分 print(int(3.14), type(int(3.14))) # 输出:3 <class 'int'> # bool -> int # True: 1, False: 0 print(int(True), type(int(True))) # 输出:1 <class 'int'>
-
float()
# 3. float() # str -> float print(float(3.14), type(float(3.14))) # 输出:3.14 <class 'float'> print(float(4), type(float(4))) # 输出:4.0 <class 'float'> # 非数字字符串无法转换为float print(float("hello"), type(float("hello"))) # could not convert string to float: 'hello' # int -> float print(float(6), type(float(6))) # 输出:6.0 <class 'float'> # bool -> float print(float(True), type(float(True))) # 输出:1.0 <class 'float'>
-
注释
-
单行注释:以 # 开头,直到换行结束
-
多行注释:并没有单独的多行注释标记,将一对三引号之间的代码称为多行注释
# 这是单行注释 """ 这 是 多行 注释 """
输入函数input()
# input()输出括号内的值,并返回用户输入的值,返回值是str类型
age = input("你今年多少岁了")
print(age, type(age)) # 输出:18 <class 'str'>
print("请输入两个加数,我来计算它们的和。")
print(int(input("第一个加数:")) + int(input("第二个加数:")))
运算符
-
算术运算符
print(1 + 1) # 加法 print(1 - 1) # 减法 print(2 * 4) # 乘法 print(10 / 3) # 除法,正常的除法。 输出:3.3333333333333335 print(10 // 3) # 整除。 输出:3 print(11 % 2) # 取余 输出:1 print(2 ** 3) # 幂,表示2的3次方 print("--------------------------------") # 特殊情况 # 整除 // # 同符号情况,正常 print(9 // 4) # 2 print(-9 // -4) # 2 # 一正一负的情况 # 这种情况下,结果需要向下取整,9除以-4的结果是-2.2,向下取整,所以结果是-3 print(9 // -4) # -3 print(-9 // 4) # -3 print("--------------------------------") # 取余 % # 同符号情况,正常 print(9 % 4) # 1 print(-9 % -4) # -1 # 一正一负的情况 # 余数 = 被除数 - (除数 * (被除数 // 除数)) # 余数 = 9 - (-4 * (9 // -4)) = 9 - (-4) * (-3) = 9 - 12 = -3 print(9 % -4) # -3 print(-9 % 4) # 3
-
赋值运算符
# 赋值运算符 # 1. 赋值执行顺序:右 -> 左 a = 3 + 4 print(a) # 7, 先右边运算,然后赋值给左边的变量 # 2. 支持链式赋值 a = b = c = 20 print(a, id(a)) # 20 2172753019728 print(b, id(b)) # 20 2172753019728 print(c, id(c)) # 20 2172753019728 # 3. 支持参数赋值: +=,-=,*=,/=,//=,%= num = 10 num /= 2 print(num) # 4. 支持系列解包赋值 a, b, c = 10, 20, 30 print(a, b, c) # 10 20 30 # 解包赋值可以使得两个变量交换值不需要临时变量 a, b = b, a print(a, b) # 20 10 # 传统做法 temp = a a = b b = temp print(a, b)
-
比较运算符
# 比较运算符,返回结果为bool类型 # 1. >,<,>=,<=,!= print(10 <= 20) # True print(10 != 20) # True # 2. == print(10 == 20) # False # == 比较的是对象的value值 a = 10 b = 10 print(a == b) # True print("--------------------------------") # 3. is,is not 相同,不相同 # is, is not 比较的是对象的id a = 10 b = 10 print(a is b) # True list1 = [1, 2, 3, 4] list2 = [5, 6, 7, 8] print(list1 is list2) # False print(id(list1)) # id: 1403208193216 print(id(list2)) # id: 1403499526848
-
布尔运算符
# and 与运算 print(1 < 2 and 2 > 3) # False # or 或运算 print(1 < 2 or 2 > 3) # True # not 非运算 print(not 1 < 2) # False # in, not in s = "hello, world" print('w' in s) # True print('k' not in s) # True list = [1, 2, 3] print(1 in list) # True
-
位运算符
# 位运算:将数据转成二进制进行计算 # 1. 位与 & # 对应数位都是1,结果位数才是1,否则为0 # 4 -> 00000100 # 8 -> 00001000 # & -> 00000000 --> 0 print(4 & 8) # 0 # 2. 位或 | # 对应数位都是0,结果数位才是0,否则为1 # | -> 00001100 --> 12 print(4 | 8) # 12 # 3. 左移位运算符 << # 每左移 1 相当于乘以 2 print(4 << 2) # 结果:16, 4 * 2 * 2 # 4. 右移位运算符 >> # 相当于除以2 print(4 >> 2) # 结果:1, 4 // 2 // 2
-
运算符优先级
()括号 -> 算术运算符(先幂,后乘除,再加减) -> 位运算符(先左移右移,再位与,位或) -> 比较运算符(>,<,>=,<=,==,!=) -> 布尔运算符(and,or) -> 赋值运算符
分支语句
-
对象的布尔值
-
Python中,所有对象都有一个布尔值,可以通过内置函数 **bool()**获取对象的布尔值
-
以下对象的布尔值为False
print(bool(False)) # False, 布尔类型False print(bool(0)) # False, 数值0 print(bool(0.0)) # False, 数值0.0 print(bool(None)) # False, None print(bool("")) # False, 空字符串 print(bool([])) # False, 空列表 print(bool(list())) # False, 空列表 print(bool(())) # False, 空元组 print(bool(tuple())) # False, 空元组 print(bool({})) # False, 空字典 print(bool(dict())) # False, 空字典 print(bool(set())) # False, 空集合
-
-
if - elif - else
score = int(input("请输入你的成绩:")) # 在python中,score >= 90 and score <= 100 可以写成:90 <= score <= 100 if 90 <= score <= 100 : print("你的成绩等级是:A+") elif 80 <= score < 90 : print("你的成绩等级是:A") elif 70 <= score < 80 : print("你的成绩等级是:A-") elif 60 <= score < 70 : print("你的成绩等级是:B") elif 0 <= score < 60 : print("你的成绩等级是:C,成绩不合格,请继续努力") else : print("请输入正确的成绩!")
-
条件表达式
- 条件表达式是 if - else 的简写
- 语法结构:
- x if 判断条件 else y
- 运算规则:
- 如果判断条件的布尔值为 True,条件表达式的返回值为 x,否则条件表达式的返回值为 False
print("请输入两个整数,我来比较它们的大小。") num1 = input("第一个数为: ") num2 = input("第二个数为: ") # 普通版 # if int(num1) > int(num2) : # print(num1 + "大于" + num2) # else : # print(num1 + "小于" + num2) # 简化版 print(num1 + "大于" + num2 if int(num1) > int(num2) else num1 + "小于" + num2)
-
pass语句
-
这个语句什么都不做,只是一个占位符,用在语法上需要语句的地方
list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] sum = 0 for i in list : # 此处的if语句没有任何作用 if i % 2 : pass sum += i print(sum) # 55
-
循环语句
-
range()函数
-
用于生成一个整数序列
-
创建range对象的三种方式
# 1. range(stop) -> 创建一个 [0, stop) 之间的整数序列,步长为默认值 1 print(range(10)) # 输出:range(0, 10) # range()的返回值是一个迭代器对象,如果想得到序列,需要通过 list(range())获得 list1 = list(range(10)) print(list1) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] # 2. range(start, stop) -> 创建一个 [start, stop) 之间的整数序列,步长为默认值 1 list2 = list(range(1, 10)) print(list2) # [1, 2, 3, 4, 5, 6, 7, 8, 9] # 3. range(start, stop, step) -> 创建一个 [start, stop) 之间的整数序列,步长为 step list3 = list(range(0, 10, 2)) print(list3) # [0, 2, 4, 6, 8]
-
优点:
- 不管range对象表示的整数序列有多长,所有range对象占用的内存空间都是相同的,因为只需要存储start,stop,step。
- 只有当用到range对象时,才会去计算序列中的相关元素
-
-
while循环语句
# 使用while计算100以内偶数和 i = 0 sum = 0 while i < 100 : sum += i i += 2 print("100以内的偶数和为:" + str(sum))
-
for - in 循环语句
# 遍历字符串 for item in "Python" : print(item) # range() 产生一个整数序列,也是一个可迭代对象 for i in range(100) : print(i) # 如果循环体中不需要使用自定义变量,可以将自定义变量写为 ”_“ for _ in range(5) : print("hello!") # 使用for-in 计算100以内偶数和 sum = 0 for i in range(0, 100, 2) : sum += i print("100以内的偶数和为:" + str(sum))
-
练习:输出100到999之间的水仙花数
# 水仙花数:一个数的每位数的三次方之和等于这个数,如:153 = 3*3*3 + 5*5*5 + 1*1*1 # 循环次数确定,所以使用for-in循环语句 # num = 153 # 个位数 # x = num % 10 # 十位数 # y = (num // 10) % 10 # 百位数 # z = num // 100 # print(x) # print(y) # print(z) for num in range(100, 1000) : x = num % 10 y = (num // 10) % 10 z = num // 100 if num == x**3 + y**3 + z**3 : print(num)
-
break 和 continue
print("你输入一些数,我来计算这些数里面的偶数和") print("输入q终止输入") sum = 0 while True: num = input("请输入:") """ 如果输入 q ,通过 break 退出循环""" if num == "q" : print("这些数里面的偶数和为:" + str(sum)) break """ 如果输入的数不是偶数,通过 continue 结束本次循环""" if int(num) % 2 != 0: continue sum += int(num)
-
else的其他用法
-
与else语句配合使用的三种情况
- 搭配 if ,当 if 条件表达式不成立时执行 else
- 搭配 while ,当没有碰到 break 时执行 else,也就是循环正常结束时执行
- 搭配 for ,同 搭配 while
# 与else语句搭配使用的三种情况 # 1. 搭配 if if int(input("请输入一个数: ")) % 2 == 0 : print("这个数是个偶数") else : print("这个数是个奇数") # 2. 搭配 while i = 0 while i < 3 : if input("请输入密码: ") == "123456" : print("密码正确,登录成功") break print("密码错误,请重新输入") i += 1 else : print("3次密码输入错误,请等候15分钟后重新输入") # 3. 搭配 for for i in range(3) : if input("请输入密码: ") == "123456" : print("密码正确,登录成功") break print("密码错误,请重新输入") else : print("3次密码输入错误,请等候15分钟后重新输入")
-
-
练习:使用双重循环打印9*9乘法表
for i in range(1, 10) : for j in range(1, i+1) : # 第二个字符串使用:end="\t" 来让print()以制表符结尾,而不是换行符结尾 print(j, "*", i, "=", i*j, end="\t") print()
列表
-
列表的创建
-
使用中括号
-
调用内置函数 list()
# 1. 列表的创建 # 使用中括号创建 list1 = ["hello", "python", 29]; # 使用 list() 函数创建 list2 = list(["world", "zhangsan", 82])
-
-
列表的特点
- 元素按顺序有序排序
- 索引映射唯一一个数据
- 可存储重复数据
- 任意数据类型混存
- 根据需要动态分配和回收内存
-
查询
# 1. 通过value获取index -> index()函数 language = ["C", "C++", "Java", "JavaScript", "Python", "Go", "Java"] # 如果列表中存在N个相同的元素,只返回相同元素中的第一个元素的索引 print(language.index("Java")) # 输出:2 # 如果查询的元素在列表中不存在,则会抛出ValueError异常 # print(language.index("C#")) # ValueError: 'C#' is not in list # 可以在指定范围进行查找 -> index(value, start, end), 注意,不包括end索引 print(language.index("Java", 3, 8)) # 6 # 2. 通过index获取value -> list[index] # 正向索引:从 0 到 N-1 print(language[2]) # Java # 反向索引:从 -N 到 -1, 最后一个元素为 list[-1] print(language[-1]) # Java # 指定索引不存在,抛出IndexError异常 print(language[7]) # IndexError: list index out of range
-
切片
# 切片语法格式:列表名[start:stop:step],切割的区间是[start, stop),不包括stop,步长为step # 1. 正向切 nums = [11, 12, 13, 14, 15, 16, 17, 18, 19] print(nums[2:7:2]) # 输出:[13, 15, 17] # 默认值:start = 0,stop = N,step = 1 print(nums[::]) # 切片返回的是一个新列表 # 可通过 nums[::] 复制列表 print(id(nums)) # 2242914473152 print(id(nums[::])) # 2243206067648 # 2. 反向切 # 默认值:start = -1,stop = -N-1, step = -1, step必须是负数才能正常切片 print(nums[-1:-8:-1]) # 可通过 反向切片 来获取逆序列表片段 print(nums[::-1]) # [19, 18, 17, 16, 15, 14, 13, 12, 11]
-
遍历
# 1. 判断指定元素在列表中是否存在 # 已注册用户 users = ["zhangsan", "lisi", "wangwu", "zhaoliu", "xiaoming"] # 登录用户 user = "qianer" # 查看登录用户是否已注册 print(user in users) # 输出:False # 2. 遍历 # 登录用户 loginUsers = ["qianer", "wangwu", "zhaoyi", "xiaoming", "zhangsan"] # 查看登录用户中哪些是已注册用户 for user in loginUsers: if user in users: print(user)
-
添加元素
# append() : 在列表末尾添加一个元素 nums = [1, 2, 3, 4, 5, 6, 7, 8, 9] nums.append(10) print(nums) # 是在原列表上添加 print(id(nums)) # id: 1714674717888 nums.append(11) print(id(nums)) # id: 1714674717888 # extend() : 在列表末尾添加一个或多个元素 nums2 = [12, 13] nums.extend(nums2) # 是在原列表上添加 print(nums, id(nums)) # nums: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] id: 1714674717888 # insert() : 在列表任意位置添加一个元素 nums.insert(0, 20) print(nums, id(nums)) # nums: [20, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], id: 1714674717888 # 切片 : 在列表的任意位置添加至少一个元素 nums[len(nums):] = [21, 22] # # 是在原列表上添加 print(nums, id(nums)) # nums: [20, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 21, 22], id: 1714674717888 # 会将nums[0]后面的元素全部截掉,然后添加[100, 101] nums[1:] = [100, 101] print(nums) # nums: [20, 100, 101]
-
删除
nums = [10, 20, 30, 40, 50, 60, 30] # 1. remove(value): 删除列表中值等于value的元素 # 重复元素只删除第一个 # 元素不存在抛出ValueError异常 nums.remove(30) print(nums) # [10, 20, 40, 50, 60, 30] # nums.remove(100) # ValueError: list.remove(x): x not in list # 2. pop(index): 删除指定索引位置的元素 # 如果索引不存在,抛出IndexError异常 # 不指定索引,删除列表最后一个元素 nums.pop(1) print(nums) # [10, 40, 50, 60, 30] # nums.pop(100) # IndexError: pop index out of range nums.pop() print(nums) # [10, 40, 50, 60] # 3. 切片: 一次删除一个或多个元素, 不过,切片后返回的是新的列表 # new_nums = nums[1:3] # print(new_nums) # [40, 50] # print(id(nums)) # 1650795074752 # print(id(new_nums)) # 1651086210496 # 不产生新的列表对象,而是删除原列表中的内容 print(id(nums)) nums[1:3] = [] print(nums) print(id(nums)) # 4. clear(): 清空列表, 清空数据,不删除对象 nums.clear() print(nums) # [] # 5. del: 删除列表,直接删除列表对象 del nums print(nums) # NameError: name 'nums' is not defined
-
修改
nums = [10, 20, 30, 40, 50, 60] # 1. 一次修改一个值 nums[2] = 100 print(nums) # [10, 20, 100, 40, 50, 60] # 2. 修改多个值 nums[1:3] = [200, 300, 400, 500] print(nums) # [10, 200, 300, 400, 500, 40, 50, 60]
-
排序
# 1. sort(): 列表的方法,对原列表操作,默认按从小到大的顺序排序 nums = [12, 39, 48, 1, 22, 8, 93] print("排序前:", nums, id(nums)) # 排序前: [12, 39, 48, 1, 22, 8, 93] 2452120392896 nums.sort() print("排序后:", nums, id(nums)) # 排序后: [1, 8, 12, 22, 39, 48, 93] 2452120392896 # 通过参数reverse=True,实现降序排序 nums. sort(reverse=True) print("降序排序:", nums) # 降序排序: [93, 48, 39, 22, 12, 8, 1] # 2. 内置函数sorted(): 产生一个新的列表,默认按从小到大排序 # 也可通过参数reverse=True,进行降序排序 new_nums = sorted(nums) print("内置函数排序:", new_nums, id(new_nums)) # 内置函数排序: [1, 8, 12, 22, 39, 48, 93] down_nums = sorted(nums, reverse=True) print("内置函数降序排序:", down_nums) # 内置函数降序排序: [93, 48, 39, 22, 12, 8, 1]
-
列表生成式
# 列表生成式,简称“生成列表的公式” # 语法格式: # [i for i in range()] nums = [i for i in range(1, 10)] print(nums) # [1, 2, 3, 4, 5, 6, 7, 8, 9] # 列表生成式的意思是,通过for-in循环遍历,并将遍历的每个 i 作为列表的元素 # 还可以对 i 运算,并将运算后的结果作为列表的元素 # 生成一个2,4,6, 8, 10的列表 even_nums = [i*2 for i in range(1, 6)] print(even_nums) # [2, 4, 6, 8, 10]
字典
-
字典的创建
# 1. 使用花括号创建 # 键需要引号,值如果是字符串则需要引号,否则不用 scores = {"张三" : 100, '李四' : 98, '小明' : 59} print(scores, type(scores)) # {'张三': 100, '李四': 98, '小明': 59} <class 'dict'> # 2. 内置函数 dict() 创建 # 内置函数创建,键不用添加单引号 students = dict(name='tomas', age=20, gender='male') # {'name': 'tomas', 'age': 20, 'gender': 'male'} print(students) # 3. 空字典 empty = {} print(empty) # {}
-
字典元素的获取
# 1. [] scores = {"张三" : 100, '李四' : 98, '小明' : 59} print(scores['张三']) # 100 # 2. get()方法 print(scores.get('张三')) # 100 # [] 和 get()的区别 # [] 如果字典中不存在指定的key,抛出KeyError异常 print(scores['王五']) # KeyError: '王五' # get() 如果字典中不存在指定的key,不抛出KeyError异常,而是返回None print(scores.get('王五')) # None # 而且,可以通过参数设置默认的value,当指定的key不存在时返回该value print(scores.get('王五', 99)) # 99
-
增删改
# key的判断:in - not in scores = {"张三" : 100, '李四' : 98, '小明' : 59} print('张三' in scores) # True print('author' not in scores) # False # 增 scores['author'] = 99 print(scores) # {'张三': 100, '李四': 98, '小明': 59, 'author': 99} # 改 scores['小明'] = 60 print(scores['小明']) # 60 # 删 del scores['小明'] # {'张三': 100, '李四': 98, 'author': 99} print(scores) # 清空 scores.clear() print(scores) # {}
-
字典的视图
# 1. keys(): 获取字典中所有的key scores = {"张三" : 100, '李四' : 98, '小明' : 59} print(scores.keys()) # dict_keys(['张三', '李四', '小明']) print(type(scores.keys())) # <class 'dict_keys'> print(list(scores.keys())) # ['张三', '李四', '小明'], 通过list()可以得到字典所有key组成的列表 # 2. values(): 获取字典中所有的value print(scores.values()) # dict_values([100, 98, 59]) print(type(scores.values())) # <class 'dict_values'> print(list(scores.values())) # [100, 98, 59] # 3. items(): 获取字典中所有键值对 print(scores.items()) # dict_items([('张三', 100), ('李四', 98), ('小明', 59)]) print(type(scores.items())) # <class 'dict_items'> print(list(scores.items())) # [('张三', 100), ('李四', 98), ('小明', 59)], 通过list()可以得到 键值对元组 列表
-
字典的遍历
scores = {"张三" : 100, '李四' : 98, '小明' : 59} # item 为字典的键 for item in scores: print(item, scores[item], scores.get(item)) # 张三 100 100 李四 98 98 小明 59 59
-
字典的特点
# 1. key不允许重复,value允许重复 scores = {'张三': 100, '张三': 60} print(scores['张三']) # 60, 当出现重复key时,后面的会覆盖前面的 # 2. key必须是不可变对象,不能使用list作为key list = [1, 2, 3, 4] scores[list] = 86 print(scores[list]) # TypeError: unhashable type: 'list' # 3. 元素是无序的 # 4. 字典可以根据需要动态地伸缩 # 5. 字典会浪费较大的内存,是一种空间换时间的数据结构
-
字典的生成式
users = ['zhangsan', 'lisi', 'wangwu'] # age = [20, 23, 21] age = [20, 23, 21, 100, 1000] # 字典的生成式 # 内置函数zip(): 用于将可迭代的对象(可遍历的对象)作为参数,将对象中对应的元素打包成一个元组,然后返回由这些元组组成的列表 # 如果两个可迭代对象的元素个数不同,会以元素个数少的为基准 userInfo = {key.title(): value for key, value in zip(users, age)} print(userInfo) # {'Zhangsan': 20, 'Lisi': 23, 'Wangwu': 21}
元组
-
可变序列和不可变序列
# 可变序列: 列表,字典 # 可变序列可以对序列执行增删改操作,对象地址不发生更改 nums = [1, 2, 3, 4] print(id(nums)) # 1729069044928 nums.append(5) print(id(nums)) # 1729069044928 # 不可变序列: 字符串,元组 str = "hello" print(id(str)) # 1729360323504 str += ", world" print(id(str)) # 1729350159408
-
元组的创建
# 1. 直接小括号 () t = ('zhangsan', '20', 'male') print(t) # 2. 内置函数 tuple() t2 = tuple(('lisi', '21', 'female')) print(t2) print(type(t2)) # 3. 只包含一个元组的元素需要使用逗号和小括号 t3 = ('zhang',) t4 = ('zhangsan') print(type(t4)) # <class 'str'>
-
元组的遍历
person = ('zhangsan', 21, 'male') # 通过索引获取 print(person[0]) # zhangsan print(person[1]) # 21 print(person[2]) # male # 遍历元组 for item in person: print(item)
集合
-
集合的创建
# 1. 通过 {} 创建 set1 = {2, 3, 3, 3, 4, 5, 5, 6, 7, 7, 7} print(set1) # {2, 3, 4, 5, 6, 7}, 集合中的元素不允许重复,会自动去重 # 2. 内置函数 set() # range() set2 = set(range(5)) print(set2) # {0, 1, 2, 3, 4} # 列表 set3 = set([1, 2, 3, 4, 2, 3, 5, 5, 6, 6]) print(set3) # {1, 2, 3, 4, 5, 6} # 元组 set4 = set((3, 4,43, 121)) print(set4) # {43, 3, 4, 121} # 字符串 set5 = set("Python") print(set5) # {'o', 't', 'P', 'h', 'n', 'y'}, 这里可以看出,集合元素是无序的 # 不可以用 {} 定义一个空集合,因为,{} 是字典 s6 = {} print(type(s6)) # <class 'dict'> # 只能通过set()定义空集合 s7 = set() print(type(s7)) # <class 'set'>
-
集合的增删改
# 1. in - not in set1 = {12, 39, 492, 43, 19, 594, 82} print(12 in set1) # True print(999 not in set1) # True # 2. 新增操作 # add() 一次添加一个元素 set1.add(999) print(999 not in set1) # False # update() 一次添加至少一个元素, 参数必须是可迭代对象 # set1.update(78, 87) print(set1) # TypeError: 'int' object is not iterable set1.update([78, 87]) print(set1) # {12, 78, 594, 19, 82, 87, 999, 39, 43, 492} # 3. 删除操作 # remove() 一次删除一个指定的元素,如果元素不存在,抛出KeyError异常 set1.remove(12) print(12 in set1) # False # set1.remove(13) # KeyError: 13 # discard() 一次删除一个指定的元素,如果元素不存在,不抛出异常 set1.discard(13) # pop() 一次只删除一个任意元素,不可以添加参数 set1.pop() print(set1) # set1.pop(19) # TypeError: set.pop() takes no arguments (1 given) # clear() 清空集合 set1.clear() print(set1) # set()
-
集合间的关系
# 相等:== != 进行判断 set1 = {10, 20, 30, 40, 50} set2 = {10, 20, 30, 40, 50} print(set1 == set2) # True # 子集:issubset() Father = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} Son = {1, 2, 3} print(Son.issubset(Father)) # True # 超集:issuperset() print(Father.issuperset(Son)) # True # 交集:isdisjoint() 注意:有交集,返回False, 无交集,返回True print(Son.isdisjoint(Father)) # False Mother = {20, 30, 40, 50} print(Father.isdisjoint(Mother)) # True
-
集合的数学操作
# 1. 交集 intersection() & s1 = {1, 2, 3, 4, 5} s2 = {3, 4, 5, 6, 7} print(s1.intersection(s2)) # {3, 4, 5} print(s1 & s2) # intersection() 与 & (与)等价,交集操作 # 2. 并集 union() | print(s1.union(s2)) # {1, 2, 3, 4, 5, 6, 7} print(s1 | s2) # union() 与 | (或)等价 # 3. 差集 difference() - 差集是 s1 去除掉 s1 和 s2 的交集 print(s1.difference(s2)) # {1, 2} print(s1 - s2) # difference() 与 - (减号)等价 # 4. 对称差集 symmetric_difference() ^ 对称差集是 s1 和 s2 的并集 减去 s1 和 s2 的交集 print(s1.symmetric_difference(s2)) # {1, 2, 6, 7} print(s1 ^ s2) # symmetric_difference() 与 ^ (按键6) 等价
-
集合的生成式
# 列表生成式 list1 = [i * i for i in range(10)] print(list1) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] # 集合生成式 # 集合生成式只是将列表生成式的 [] 改成 {} set1 = {i * i for i in range(10)} print(set1) # {0, 1, 64, 4, 36, 9, 16, 49, 81, 25}
数据结构总结
字符串
-
字符串驻留机制
-
仅保存一份相同且不可变字符串的方法,不同的值被存放在字符串的驻留池中,Python的驻留机制对相同的字符串只保留一份拷贝,后续创建相同字符串时,不会开辟新空间,而是把该字符串的地址赋给新创建的变量
-
驻留机制的几种情况(交互模式,即windows的命令行模式中使用python)
# 1. 字符串的长度为0或1时 >>> a='a' >>> b='a' >>> a is b True # 2. 符合标识符的字符串(字母,数字,下划线组成) >>> a='abc%' # % 不符合 >>> b='abc%' >>> a is b False >>> a='abc_' >>> b='abc_' >>> a is b True # 3. 字符串只在编译时进行驻留,而非运行时 >>> a='abc' >>> b='ab' + 'c' >>> c=''.join(['ab', 'c']) # join() 为运行时 >>> a is b True >>> a is c False # 4. [-5, 256]之间的整数数字 >>> a=-5 >>> b=-5 >>> a is b True >>> a=-6 >>> b=-6 >>> a is b False
-
sys 模块中的 intern() 方法可以强制2个字符串指向同一个对象
>>> import sys >>> a='abc%' >>> b='abc%' >>> a is b False >>> a=sys.intern(b) >>> a is b True
-
PyCharm 对字符串进行了优化处理,上述4中情况在PyCharm中不一定适合
# 1. 对于条件1, 不适用 a = '%%' b = '%%' print(a is b) # True # 2. 对于条件2,不适用 a = 'aaaaaaaaaaaaaaaaaaaaaaaaaa' b = 'aaaaaaaaaaaaaaaaaaaaaaaaaa' print(a is b) # True # 3. 对于条件3,适用 x = 'abc' y = 'ab' + 'c' z = ''.join(['ab', 'c']) print(x is y) # True print(x is z) # False # 4. 对于条件4,不适用 num1 = -9999 num2 = -9999 print(num1 is num2) # True
-
在需要进行字符串拼接时,建议使用 str 类型的 join() 方法,而非 + ,因为 join() 方法是先计算出所有字符中的长度,然后再拷贝,只 new 一次对象,效率要比 + 效率高
-
-
字符串的查找
# 1. index(substr) 查找子串 substr 第一次 出现的位置,如果查找的子串不存在,抛出 ValueError 异常 str1 = "hello, hello" print(str1.index("lo")) # 3, 返回 l 所在的索引 # print(str1.index("hi")) # ValueError: substring not found # 2. rindex(substr) 查找子串 substr 最后一次 出现的位置,如果查找的子串不存在,抛出 ValueError 异常 print(str1.rindex("lo")) # 10 # print(str1.rindex("hi")) # ValueError: substring not found # 推荐使用 find() 和 rfind() 查找字符串 # 3. find(substr) 查找子串 substr 第一次 出现的位置,如果查找的子串不存在,返回 -1 print(str1.find("lo")) # 3 print(str1.find("k")) # -1 # rfind(substr) 查找子串 substr 最后一次 出现的位置,如果查找的子串不存在,返回 -1 print(str1.rfind("lo")) # 10 print(str1.rfind("hi")) # -1
-
字符串的大小写操作
str1 = "hello, World" # 1. upper(): 把字符串中所有字符都转成 大写 字母 upperStr = str1.upper() # 返回一个新的字符串对象 print(upperStr) # HELLO, WORLD # 2. lower(): 把字符串中所有字符都转成 小写 字母 lowerStr = str1.lower() print(lowerStr) # hello, world # 3. swapcase(): 把字符串中所有 大写 字母 转成 小写,把 小写 转成 大写 swapcaseStr = str1.swapcase() print(swapcaseStr) # HELLO, wORLD # 4. capitalize(): 把 第一个 字符转换成大写,其余的转换为小写 capitalizeStr = str1.capitalize() print(capitalizeStr) # Hello, world # 5. title(): 把每个单词的 第一个字符转换为 大写,把每个单词 剩余字符转换为 小写 titleStr = str1.title() print(titleStr) # Hello, World
-
字符串的对齐方式
# 对齐方式方法,第一个参数指定宽度,第2个参数指定填充符,第2个参数可选,默认为空格,如果宽度小于实际宽度,则返回原字符串 str1 = "Hello, Python" # 1. center(): 居中对齐 print(str1.center(20, "#")) # ###Hello, Python#### # 2. ljust(): 左对齐 print(str1.ljust(20, "#")) # Hello, Python####### # 3. rjust(): 右对齐 print(str1.rjust(20, "#")) # #######Hello, Python # 如果指定宽度小于实际宽度,则返回原字符串 print(str1.rjust(10, "#")) # Hello, Python # zfill(): 右对齐,左边用 0 填充,只接收一个参数,用于指定字符串的宽度,如果宽度小于等于字符串的长度,返回字符串本身 print(str1.zfill(20)) # 0000000Hello, Python # 数字有点特殊 print("12345".zfill(10)) # 0000012345 print("-12345".zfill(10)) # -000012345 , 从 - (负号)后面开始填充
-
字符串的劈分
# 1. split() # 从字符串的左边开始劈分,默认的劈分字符是空格,返回的值是一个列表 # 通过参数 sep 指定劈分字符串的劈分符 # 通过参数 maxsplit 指定劈分字符串时的最大劈分次数,在经过最大劈分次数后,剩余的子串会单独作为一份 str1 = "Hello world Python" print(str1.split()) # ['Hello', 'world', 'Python'] str2 = "Hello|world|Python" print(str2.split(sep='|')) # ['Hello', 'world', 'Python'] print(str2.split(sep='|', maxsplit=1)) # ['Hello', 'world|Python'] # 2. rsplit(): 从右边开始劈分,参数和作用同上 print(str2.rsplit(sep='|', maxsplit=1)) # ['Hello|world', 'Python']
-
字符串判断的相关操作
# 1. isidentifier(): 判断指定的字符串是否是合法的标识符 print("abc%".isidentifier()) # False # 2. isspace(): 判断指定的字符串是否 全部 由 空白字符组成(回车、换行、水平制表符) print("\t".isspace()) # True # 3. isalpha(): 判断指定的字符串是否 全部 由 字母 组成 print("abc1".isalpha()) # False # 4. isdecimal(): 判断指定的字符串是否 全部 由 十进制 的数字组成 print("1234".isdecimal()) # True # 5. isnumeric(): 判断指定的字符串是否 全部 由 数字 组成 print("123四".isnumeric()) # True # 6. isalnum(): 判断指定的字符串是否 全部 由 字母和数字 组成 print("abc四".isalnum()) # True
-
字符串的替换和合并
# 1. replace(): 第1个参数 -> 被替换的子串,第2个参数 -> 替换子串的字符串, 第3个参数 -> 最大替换次数。该方法返回替换后的字符串 str1 = "Hello Python Python Python" newStr = str1.replace("Python", "Java", 2) print(newStr) # Hello Java Java Python # 2. join(): 将列表或元组中的字符串合并成一个字符串 strs = ["hello", "Python", "Hello", "Java"] joinStr = " ".join(strs) # 用 “ ” 将列表中的元素拼接到一起 print(joinStr) # hello Python Hello Java strTuple = ("C", "Python", "Java") print(" | ".join(strTuple)) # C | Python | Java str = "Python" print("*".join(str)) # P*y*t*h*o*n, 字符串也是列表
-
字符串的比较
# 运算符:> , < , >= , <= , == , != # 比较规则:首先比较两个字符串的第一个字符,如果相等,则继续比较下一个字符,依次比较下去。 # 直到两个字符串的字符不相等,其比较结果就是两个字符串的比较结果。 # 两个字符串中所有后续字符将不再比较 # 比较原理:两个字符比较时,比较的是其 ordinal value (原始值),调用内置函数 ord() ,可以得到指定字符的 ordinal value。 # 与内置函数 ord() 对应的是内置函数 chr() ,调用内置函数 chr() 时指定 ordinal value可以得到其对应的字符 print("alpha" > "alp") # True print("alpha" > "banana") # False print(ord("a"), ord("b")) # 97 98 因为第一个字符 a 的 ordinal value 比 b 小,所以 "alpha" < "banana" print(chr(97), chr(98)) # a b # == 和 is 的区别: == 比较的是 value,is 比较的是 id a = b = "Python" c = "".join("Python") print(a == b) # True print(a is b) # True print(a == c) # True print(a is c) # False
-
字符串的切片
# 字符串是不可变类型,所以不具备增删改等操作,而且,切片操作将产生新的对象 s = "Hello, Python" s1 = s[:5] # 由于没有指定起始位置,所以默认从 0 开始 s2 = s[6:] # 由于没有指定结束位置,所以切到字符串的最后一个元素 s3 = " #" print(s1 + s3 + s2) # Hello # Python # s[start: end: step] print(s[1: 5: 1]) # ello , 从1开始,截取到5 (不包含5),步长为1 print(s[::2]) # Hlo yhn , 没指定起始位置和结束位置,按默认的从0开始截取到最后一个元素,步长为2 print(s[::-1]) # nohtyP ,olleH, 默认从字符串最后一个元素开始,到字符串的第一个元素结束,因为步长为负数 print(s[-6::1]) # Python , 从索引-6开始,到字符串的最后一个元素结束,步长为1,所以,步长决定截取的方向,而不是由索引决定
-
字符串的格式化
# 1. % 占位符 %s -> 字符串, %d 或 %i -> 整数, %f -> 浮点数 name = "Tomas" age = 20 print("我叫%s,今年%d岁" % (name, age)) # 指定宽度 print("%10d" % 99) # 99, 10表示宽度,在99的前面填充了8个空格 # 指定精度 print("%f" % 3.1415926) # 3.141593 , 默认小数点后6位 print("%.10f" % 3.1415926) # 3.1415926000 print("%.3f" % 3.1415926) # 3.142, .3 表示小数点后3位,会四舍五入 # 同时指定宽度和精度 print("%10.3f" % 3.1415926) # 3.142, 总共10宽度,并保留小数点后3位 # 2. {} 占位符 print("我叫{0},今年{1}岁".format(name, age)) # {} 里面的数字代表是format() 中的第几个变量,从0开始 # 另一种写法:f-string print(f"我叫{name},今年{age}岁") # 指定宽度 print("{:10}".format(99)) # 99, 总共10宽度 # 指定精度 print("{0:.3}".format(3.1415926)) # 3.14, .3 表示一共3位数,注意,是一共,会四舍五入 print("{:.3f}".format(3.1415926)) # 3.142, .3f 表示是3位小数,会四舍五入 # 同时指定宽度和精度 print("{:10.3f}".format(3.1415926)) # 3.142
-
字符串的编码和解码
# 1. 编码:将字符串转换成二进制数据(bytes) s = "你好啊" print(s.encode("utf-8")) print(s.encode(encoding="utf-8")) # utf-8 编辑格式,一个中文占三个字节 print(s.encode("gbk")) print(s.encode(encoding="gbk")) # gbk 编辑格式,一个中文占两个字节 # 2. 解码:将bytes类型的数据转换成字符串类型 b = s.encode("utf-8") print(b.decode(encoding="utf-8")) # 你好啊 # 不能将一种格式的编码 解码成另一种格式的 print(b.encode(encoding="gbk")) # AttributeError: 'bytes' object has no attribute 'encode'. Did you mean: 'decode'?
字符串总结
函数
-
函数的创建
# 创建格式 # def functionName(参数列表): # functionBody # [ return result ] 这部分可省略 # 创建函数 def sum(x, y): result = x + y return result # 调用函数: functionName(参数) result = sum(10, 20) print(result) # 30
-
函数的参数传递
def sum(a, b): return a + b # 1. 位置实参:根据形参的对应位置进行实参传递 print(sum(10, 20)) # 30, 这里直接给的实参,那么实参会按顺序赋值给对应位置的形参,一个萝卜一个坑 # 2. 关键字实参:根据形参名称进行实参传递 print(sum(b = 10, a = 20)) # 30, 直接指明了哪个形参的值是多少,点名道姓
-
函数的返回值
# 1. 如果函数没有返回值,即函数执行完毕后,不需要给调用者返回数据,return 可以省略不写 def sayHello(): print("Hello") sayHello() # 2. 函数的返回值有 1 个,直接返回原类型 def appendList(args): args.append(99) return args args = [10, 12, 11, 13, 19, 89] print(type(appendList(args))) # <class 'list'> # 3. 函数的返回值有 多个,返回的结果是 元组 def oddOrEven(args): odd = [] even = [] for i in args: if i % 2: odd.append(i) else: even.append(i) return odd, even print(oddOrEven(args)) # ([11, 13, 19, 89, 99], [10, 12])
-
函数定义默认值参数
# 函数定义时,给形参设置默认值,只有与默认值不符的时候才需要传递实参 def fun(a, b = 10): return a + b print(fun(20)) # 30, 只给了一个实参,所以 形参b 取默认值 print(fun(20, 50)) # 70, 给了两个实参,所以 形参b 使用传递的实参 50
-
个数可变的形参
# 个数可变的位置参数 # 1. 定义函数时,可能无法事先确定传递的位置实参的个数时,使用可变的位置参数 # 2. 使用 * 定义个数可变的位置形参 # 3. 结果为一个 元组 def fun1(*args): print(args) fun1(10, 20, 30) # (10, 20, 30) # 个数可变的关键字形参 # 1. 定义函数时,可能无法事先确定传递的位置实参的个数时,使用可变的关键字形参 # 2. 使用 ** 定义个数可变的关键字形参 # 3. 结果为一个 字典 def fun2(**args): print(args) fun2(a = 1, name = "zhangsan", age = 20) # {'a': 1, 'name': 'zhangsan', 'age': 20} # 个数可变的位置形参,只能有 1 个 # def fun3(*args1, *args2): # SyntaxError: invalid syntax # pass # 个数可变的关键字形参,只能有 1 个 # def fun4(**args1, **args2): # SyntaxError: invalid syntax # pass # 如果既有个数可变的 关键字形参,又有个数可变的 位置形参,要求:个数可变的位置形参,放在个数可变的关键字形参之前 # def fun5(**args1, *args2): # SyntaxError: invalid syntax # pass # 个人理解,* 和 ** 就像是个打包和解包的符号,将参数个数可变的参数都打包成一个元组 或 字典 # 也可以通过 * 和 ** 将元组、列表、字典解包 def fun(a, b, c): print(a, b, c) fun(10, 20, 30) # 10 20 30 # 通过 * 将元组 或 列表解包 tuple1 = (11, 12, 13) list1 = [21, 22, 23] fun(*tuple1) # 11 12 13 fun(*list1) # 21 22 23 # 通过 ** 将 字典 解包 dict1 = {'a': 1, 'b': 2, 'c': 3} fun(**dict1) # 1 2 3 # 此时,字典中的键值对必须符合关键字实参,也就是说,键必须和函数的形参一样 dict2 = {'a': 1, 'b': 2, 'name': 3} fun(**dict2) # TypeError: fun() got an unexpected keyword argument 'name'
-
变量的作用域
# 局部变量 def say(): args = "Hello" print(args) # args 在函数内定义的,是局部变量 # print(args) # NameError: name 'args' is not defined # 可以通过关键字 global 将局部变量变为全局变量 def say2(): global str str = "Python" print(str) # 不过要先调用该函数,才能全局使用该变量 say2() print("Hello, " + str) # Hello, Python # 全局变量: 函数外定义的变量 name = "zhangsan" def printStr(): print(name) printStr() # zhangsan
-
递归函数
# 递归函数应该由 递归条件 和 终止条件 组成 # 用递归计算阶乘 def factorial(num): if num == 1: return 1 return num * factorial(num -1) print(factorial(6)) # 用递归算斐波那契数 # 斐波那契数:前两个斐波那契数之和 def Fibonacci(num): if num == 0: return 0 elif num == 1: return 1 return Fibonacci(num - 1) + Fibonacci(num - 2) # 1 1 2 3 5 8 13 21 34 print(Fibonacci(10))
异常
-
try - except 结构
# 一个交互式计算两个整数之和的程序 # 如果用户不小心输入第二个整数时输入0,0是不能作为除数的,会报 ZeroDivisionError 错误 # 因此,可以使用 try - except 对异常进行捕获,输出让用户理解的错误信息 try: n1 = int(input("请输入一个整数: ")) n2 = int(input("请输入另一个整数: ")) result = n1 / n2 print("这两个整数的和为: ", result) except ZeroDivisionError: print("不好意思,除数不能为0")
-
try - except - except 多 except结构
# 使用 try - except 解决输入除数为0的情况,不过,当用户输入的不是数值类型时,会报 ValueError 错误 # 可以使用多个 except 捕获不同的异常 # 多个 except 结构:捕获异常的顺序按照先子类后父类的顺序,为了避免遗漏可能出现的异常,可以在最后增加 BaseException try: n1 = int(input("请输入一个整数: ")) n2 = int(input("请输入另一个整数: ")) result = n1 / n2 print("这两个整数的和为: ", result) except ZeroDivisionError: print("不好意思,除数不能为0") except ValueError: print("不好意思,请输入整数") except BaseException: print("未知错误,请通知管理员")
-
try - except - else 结构
# try - except - else 结构:如果try块中没有抛出异常,则执行else块,如果try中抛出异常,则执行except块 try: n1 = int(input("请输入一个整数: ")) n2 = int(input("请输入另一个整数: ")) result = n1 / n2 print("这两个整数的和为: ", result) except ZeroDivisionError: print("不好意思,除数不能为0") except ValueError: print("不好意思,请输入整数") except BaseException: print("未知错误,请通知管理员") else: print("这两个整数的和为: ", result)
-
try - except - else - finally 结构
# try - except - else - finally 结构:finally块无论是否发生异常,都会执行,常用来释放try块中申请的资源 try: n1 = int(input("请输入一个整数: ")) n2 = int(input("请输入另一个整数: ")) result = n1 / n2 except ZeroDivisionError: print("不好意思,除数不能为0") except ValueError: print("不好意思,请输入整数") except BaseException: print("未知错误,请通知管理员") else: print("这两个整数的和为: ", result) finally: print("感谢您的使用")
-
获取异常信息
try: n1 = int(input("请输入一个整数: ")) n2 = int(input("请输入另一个整数: ")) result = n1 / n2 except ZeroDivisionError as e: print(e) # division by zero print("不好意思,除数不能为0")
-
常见的异常类型
-
traceback 模块
# 使用 traceback 模块打印异常信息,常用于保存日志信息 import traceback try: print("==================================") print(1 / 0) except: traceback.print_exc()
类与对象
-
类的创建 和 对象的创建
# 类的创建 class Student: # 类属性 address = "湖南" # 初始化方法 (构造函数) def __init__(self, name, age): self.name = name # self.name 称为实例属性 self.age = age # 实例方法 def eat(self): print(self.name, "正在吃饭。。。") # 静态方法 # 使用 @staticmethod 注解,形参中不需要添加 self @staticmethod def static(name): print("这是一个静态方法", name) # 类方法 # 使用 @classmethod 注解,形参中必须添加 cls ,这是 class的缩写 @classmethod def cm(cls): print("这是一个类方法") # 对象的创建 student1 = Student("zhangsan", 20) # 对象调用方法的两种方式 student1.eat() Student.eat(student1)
-
类属性、类方法、类静态方法
# 类属性:类中且方法外的变量称为类属性,被该类的所有对象共享 student2 = Student("lisi", 21) print(student1.address, student2.address) # 湖南 湖南 # 类方法:使用 @classmethod 修饰的方法,使用类名直接访问的方法 Student.cm() # 这是一个类方法 # 静态方法:使用 @staticmethod 修饰的方法,使用类名直接访问的方法,没有默认形参,类方法有默认形参 cls Student.static(student1.name) # 这是一个静态方法 zhangsan
-
对象的动态绑定
# 对象动态绑定属性和方法 # 1. 动态绑定属性 student1.gender = 'male' print(student1.gender) # male # 只对添加了属性的对象生效,并不是给类添加了属性 # print(student2.gender) # AttributeError: 'Student' object has no attribute 'gender' # 2. 动态绑定方法 def show(name): print(name, "说:这是一个动态绑定的方法") # 动态绑定方法时,不用加 () student1.show = show student1.show(student1.name) # zhangsan 说:这是一个动态绑定的方法
-
面向对象三大特性
-
封装
# 封装 # 1. 将属性和方法包装在类对象中。在方法内部对属性进行操作,在类对象的外部调用方法。 # 这样,无需关系方法内部的具体实现细节,从而隔离了复杂度 # 2. 在Python中没有专门的修饰符用于属性的私有,如果不希望在类对象外部被访问,前面使用两个 _ (下划线) class Student: def __init__(self, name, age): self.name = name self.__age = age # age 属性前面添加两个 _ (下划线),将属性设置为私有 def show(self): print("我叫{},今年{}岁了".format(self.name, self.__age)) # age 属性在类内可以访问 stu1 = Student("zhangsan", 20) # 无法通过 objectName.attribute 的形式来访问私有属性 # print(stu1.__age) # AttributeError: 'Student' object has no attribute '__age' stu1.show() # 不过,Python 中并没有真正意义上的私有属性 # 内置函数 dir(object): 可以获取对象的所有属性,包括 __ 开头的属性。 print(dir(stu1)) # 从中发现,__age属性的名称为_Student__age print(stu1._Student__age) # 20, 可以通过 stu1._Student__age 访问私有属性 __age # 类中声明的私有属性可以通过 _className__私有属性 的方式访问。 # 所以,Python中没有私有属性,把 __ 开头的属性作为私有属性的含义只是一种约定俗成,当程序员发现属性为 __ 开头,就把它当成私有属性就好了
-
继承
# 继承:提高代码的复用性 # 如果一个类没有继承任何类,则默认继承object # class Father(object): class Father(): def __init__(self, name, age): self.name = name self.age = age def show(self): print("我叫{},今年{}岁".format(self.name, self.age)) class Mother(): def __init__(self, gender): self.gender = gender def play(self, hobbit): print("我喜欢{}".format(hobbit)) # 继承的语法格式: # class 子类(父类): class Son(Father): def __init__(self, name, age, hobbits): # 定义子类时,必须在其构造函数中调用父类的构造函数。没规定父类构造函数必须是第一行 super().__init__(name, age) self.hobbits = hobbits # 方法重写 def show(self): # 可使用 super().父类的方法 来使用重写前的方法 super().show() print("我是子类,我重写了父类") son1 = Son("cxk", 20, "唱,跳,rap,篮球") # 子类继承了父类的方法 son1.show() # 方法重写后,调用show()方法 son1.show() # Python支持多继承 class Child(Father, Mother): def __init__(self, name, age, gender, hobbit): # 调用父类的初始化方法,需要传入 self Father.__init__(self, name, age) Mother.__init__(self, gender) self.hobbit = hobbit child1 = Child("cxk", 20, "male", "唱,跳,rap, 篮球") child1.show() child1.play(child1.hobbit)
-
多态
class Animal(): """动物类""" def __init__(self): pass def eat(self): print("正在吃东西...") class Cat(Animal): """猫咪类,继承动物类""" def __init__(self): pass def eat(self): print("猫咪正在吃鱼...") class Dog(Animal): """狗狗类,继承动物类""" def __init__(self): pass def eat(self): print("狗狗正在吃骨头...") class Person(): """人类""" def __init__(self): pass def eat(self): print("人正在吃饭...") def fun(obj): """执行obj对象的eat()方法""" obj.eat() # 多态:即 ”具有多种形态“,指的是:即便不知道一个变量所引用的对象到底是什么类型,仍然可以通过这个变量调用方法, # 在运行过程中根据变量所引用的对象的类型,动态决定调用哪个对象的方法 fun(Animal()) # 正在吃东西... fun(Cat()) # 猫咪正在吃鱼... fun(Dog()) # 狗狗正在吃骨头... # 注意 # 静态语言和动态语言关于多态的区别 # 静态语言(如Java)实现多态的三个必要条件 # 1. 继承 # 2. 方法重写 # 3. 父类引用指向子类对象 # 动态语言(如Python)的多态崇尚 ”鸭子类型“ :当看到一只鸟走起来像鸭子、游泳起来像鸭子,那么这只鸟就可以被称为鸭子。 # 在鸭子类型中,不需要关心对象是什么类型,到底是不是鸭子,只关心对象的行为 # Person类并不是Animal类的子类,但Person类也有 eat() 方法,因此也符合动态语言的多态 fun(Person()) # 人正在吃饭...
-
-
object 类
# object类是所有类的父类,因此,所有类都有object类的属性和方法 # 1. 内置函数 dir() : 可以查看指定对象所有属性 class Student: def __init__(self, name, age): self.name = name self.age = age """重写__str__()方法""" def __str__(self): return "我的名字是{},今年{}岁".format(self.name, self.age) stu = Student("zhangsan", 20) print(dir(stu)) # 2. object有一个 __str__() 方法,用于返回一个对于 ”对象的描述“,类似于Java中的toString()方法 # 对应于内置函数 str(),经常用于print()方法,帮助查看对象的信息,所以经常会对__str__() 进行重写 # 未重写 __str__() 方法时,打印信息为 对象的类型 和 对象的地址 print(stu) # <__main__.Student object at 0x00000207569290C0>,直接print(对象),默认调用对象的__str__() 方法 # 重写 __str__() 方法后,打印重写后的 return 返回的信息 print(stu) # 我的名字是zhangsan,今年20岁
-
特殊属性
class A: def __init__(self): pass class B: def __init__(self): pass class C(A, B): def __init__(self, name, age): self.name = name self.age = age # 特殊属性 c = C("zhangsan", 20) print(c.__dict__) # 实例对象的属性字典 print(C.__dict__) # 类的属性字典 print(c.__class__) # 对象所属的类 print(C.__bases__) # C 类的父类类型的元组 print(C.__base__) # C 类的基类,基类根据 类声明中 class C(A, B): 括号内哪个类在前面,哪个类就是基类 print(C.__mro__) # 类的层次结构,也就是类的继承结构 print(A.__subclasses__()) # 类的子类列表
-
特殊方法
# 1. __add__() 方法 a = 10 b = 20 c = a + b print(c) # 两个整数之所以可以通过 ” + “ 作相加操作,是因为整数有__add__()方法 d = a.__add__(b) # 等同于 a + b print(d) class Student: def __init__(self, name, age): self.name = name self.age = age """重写__add__()方法""" def __add__(self, other): return self.age + other.age """重写__len__()方法""" def __len__(self): return len(self.name) stu1 = Student("zhangsan", 20) stu2 = Student("lisi", 21) # 对象之间无法使用 "+" 相加操作 stu3 = stu1 + stu2 # TypeError: unsupported operand type(s) for +: 'Student' and 'Student' # 可以通过重写 __add__() 方法,使自定义的对象具有 "+"功能 stu4 = stu1 + stu2 stu5 = stu1.__add__(stu2) print(stu4, stu5) # 41 41 # 2. __len__() 方法 # 列表可以使用内置函数 len() 来获取列表的长度, 而Student对象却会报错 list1 = [1, 2, 3, 4, 6] print(len(list1)) # print(len(stu1)) # TypeError: object of type 'Student' has no len() # 这是因为列表重写了__len__()方法 print(list1.__len__()) # 通过重写__len__()方法,让内置函数len()的参数可以是自定义对象的类型 print(len(stu1)) # 8 print(len(stu2)) # 4
# 特殊方法 __new__() 和 __init__() class Person(): def __new__(cls, *args, **kwargs): print("__new__方法被调用,cls的id值为: {}".format(id(cls))) obj = super().__new__(cls) print("创建的对象的id值为: {}".format(id(obj))) return obj def __init__(self, name, age): print("__init__方法被调用,self的id值为: {}".format(id(self))) self.name = name self.age = age print("object 类的id值为: {}".format(id(object))) print("Person 类的id值为: {}".format(id(Person))) # 创建Person类的实例对象 p1 = Person("zhangsan", 20) print("p1 这个Person类的实例对象的id值为: {}".format(id(p1))) # 由上面的代码的输出内容以及debug可知, # 执行 p1 = Person("zhangsan", 20) 时, # 先调用Person类的__new__()方法,其中参数cls = Person类,args = ["zhangsan", 20],所以cls的id值和Person类的id值相同 # 然后调用父类object的__new__()方法,传入cls,返回一个对象, # 接着,会调用__init__()方法,将刚创建的obj和agrs中的值传入,所以 self 和 obj 的id值一样。 # __init__()方法执行完之后,会将生成的对象赋值给p1
-
对象的拷贝
# 变量的赋值 # 只是形成两个变量,实际上还是指向同一个对象 a = 100 b = a print(id(a), id(b)) class CPU(): def __init__(self): pass class Disk(): def __init__(self): pass class Computer(): def __init__(self, cpu, disk): self.cpu = cpu self.disk = disk # 浅拷贝 # Python拷贝一般是浅拷贝,拷贝时,对象包含的子对象的内容不拷贝,因此,源对象与拷贝对象会引用同一个子对象 cpu = CPU() disk = Disk() computer = Computer(cpu, disk) # 对象的拷贝需要导入copy模块 import copy computer2 = copy.copy(computer) # 打印输出的id值,computer 和 computer2的id不同,但两对象的cpu属性和disk属性的id值相同 # 浅拷贝只拷贝了一份引用,并没有拷贝一份子对象 print(id(computer), id(computer.cpu), id(computer.disk)) print(id(computer2), id(computer2.cpu), id(computer2.disk)) # 深拷贝 # 使用copy模块的deepcopy函数,递归拷贝对象中包含的子对象,源对象和拷贝对象所有的子对象也不相同 computer3 = copy.deepcopy(computer) print(id(computer), id(computer.cpu), id(computer.disk)) print(id(computer3), id(computer3.cpu), id(computer3.disk))
模块
-
导入模块
# import 模块名 [as 别名] # 导入的是整个模块 import math as m print(m.pi) print(m.pow(2, 2))
# from 模块名 import 函数/变量/类 # 导入的是模块的部分,导入多个用 , 隔开 # 未导入的内容无法访问 from math import pow print(pow(2, 10)) print(pi) # NameError: name 'pi' is not defined
-
主程序
# 主程序 # 在每个模块的定义中,都包括一个记录模块名称的变量 __name__ ,程序可以检查该变量,以确定它们在哪个模块中执行。 # 如果一个模块不是被导入到其他程序中执行,那么它可能在解释器的顶级模块中执行 # 顶级模块的 __name__ 变量的值为 __main__ import math def perimeter(r): """计算圆的周长""" return 2 * r * math.pi # 这条语句相当于Java中的main方法 if __name__ == '__main__': print(perimeter(4).__floor__())
-
常用的模块
-
第三方模块的安装和使用
-
安装
-
在终端中使用命令:pip install 模块名
-
-
使用
import schedule import time def job(): print("哈哈哈哈") # schedule 是一个定时任务模块,可用于定时发送邮件等业务 schedule.every(3).seconds.do(job) # 每三秒执行一次 job() 方法 while True: schedule.run_pending() time.sleep(1) # 停顿 1 秒
-
包
-
Python中的包
- 包是一个分层次的目录结构,它将一组功能相近的模块组织在一个目录下
- 作用:
- 代码规范
- 避免模块名称冲突
-
包和目录的区别
- 包含 " __ init __.py"文件的目录称为包
- 目录中通常不包含 "__ init __.py"文件
-
包的导入
# import 方式导入 # 使用 import 方式进行导入时,只能跟 包名或模块名 # import package1.moduleA import package1.moduleA as A # 这样使用value值需要 包名.模块名.变量 # 可以在导入包或模块时,给包或模块一个别名 # print(package1.moduleA.value) print(A.value) # from...import... 方式导入 # 使用 from... import... 方式导入时,可以导入包、模块、函数、变量 from package1.moduleB import value print(value)
文件
-
编码格式
-
Python的解释器使用的是 Unicode (内存)
-
.py 文件在磁盘上使用的是 UTF-8 (外存)
-
在 .py 文件 中,可以通过在第一行添加 # encoding = “” 来指定编码格式
# encoding= gbk """ @title: @description: 文件的编码格式 @date: 2022/11/3-20:20 """
-
-
内置函数open()
# 内置函数open()创建文件对象 # 语法规则:file = open(filename [, mode, encoding]) # filename : 要创建或打开的文件名称 # mode : 打开模式,默认是只读 # encoding : 默认文本文件中字符的编码格式为gbk # file : 被创建的文件对象 file = open("test.txt", "r", encoding="utf-8") # 由于 test.txt 文件默认编码格式是gbk,不添加encoding = "utf-8" 会报错 print(file.readlines()) # ['你好,世界\n', 'Python'] , 返回的是一个列表 file.close()
-
文件的打开模式
-
文件的类型:
- 按文件中数据的组织形式,文件分为以下两大类
- 文本文件:存储的是普通的 “字符” 文本,默认为 Unicode 字符集,可以使用记事本程序打开
- 二进制文件:把数据内容用 “字节” 进行存储,无法用记事本打开,必须使用专用的软件打开,举例:mp3音频文件,jpg图片,.doc 文档等
- 按文件中数据的组织形式,文件分为以下两大类
-
打开模式
# w 模式 file_W = open("test.txt", "w", encoding="utf-8") file_W.write("Java") file_W.close() # a 模式 file_A = open("test.txt", "a", encoding="utf-8") file_A.write(" Python") file_A.close() # b 模式,b 模式不能单独使用,需要和其他模式一起使用,如 rb、wb,常用于二进制文件的复制 src_file = open("LaPluma.png", "rb") target_file = open("CopyLaPluma.png", "wb") target_file.write(src_file.read()) target_file.close() src_file.close()
-
-
文件对象的常用方法
-
with 语句 (上下文管理器)
-
with 语句可以自动管理上下文资源,不论什么原因跳出with块,都能确保文件的正确关闭,以此来达到释放资源的目的
-
原理
-
代码演示
# 语法格式: # with 上下文表达式 as 上下文管理器的引用: # with 语句体 # 上下文表达式:该表达式的结果为一个 上下文管理器,同时会自动调用该上下文管理器的 __enter__()方法,并将返回值赋值给 上下文管理器引用 # 上下文管理器:一个类,实现了 __enter__() 方法和 __exit__() 方法,则这个类遵守了 上下文管理协议,那么这个类就是一个上下文管理器 # 当 with 块执行完后,会自动调用 上下文管理器的 __exit__() 方法 class MyContentManager(object): def __enter__(self): print("enter方法被调用了") # 这里要返回对象,不然会报错:AttributeError: 'NoneType' object has no attribute 'show' # 因为执行到上下文表达式之后,要将该上下文管理器的引用赋值给 as 后的引用 return self def __exit__(self, exc_type, exc_val, exc_tb): # 除self 参数外,还必须要这三个参数 print("exit方法被调用了") def show(self): print("show方法被调用了") with MyContentManager() as file: # 这句相当于是:file = MyContentManager() file.show() # 用 with块实现图片的复制 with open("LaPluma.png", "rb") as src_file: with open("CopyLaPluma2.png", "wb") as target_file: target_file.write(src_file.read())
-
OS 模块
-
os 模块是Python内置的与操作系统功能和文件系统相关的模块。
-
该模块中的语句的执行结果通常与操作系统有关,在不同的操作系统上允许,得到的结果可能不一样
-
os 模块 与 os.path 模块用于对目录或文件进行操作
-
os 模块的常用函数
-
os.path 模块 操作目录相关的函数
coding = “utf-8” 会报错
print(file.readlines()) # [‘你好,世界\n’, ‘Python’] , 返回的是一个列表
file.close()
* 文件的打开模式
* 文件的类型:
* 按文件中数据的组织形式,文件分为以下两大类
1. **文本文件**:存储的是普通的 “字符” 文本,默认为 Unicode 字符集,可以使用记事本程序打开
2. **二进制文件**:把数据内容用 “字节” 进行存储,无法用记事本打开,必须使用专用的软件打开,举例:mp3音频文件,jpg图片,.doc 文档等
* 打开模式
[外链图片转存中...(img-pmBgx7q0-1679489217514)]
~~~python
# w 模式
file_W = open("test.txt", "w", encoding="utf-8")
file_W.write("Java")
file_W.close()
# a 模式
file_A = open("test.txt", "a", encoding="utf-8")
file_A.write(" Python")
file_A.close()
# b 模式,b 模式不能单独使用,需要和其他模式一起使用,如 rb、wb,常用于二进制文件的复制
src_file = open("LaPluma.png", "rb")
target_file = open("CopyLaPluma.png", "wb")
target_file.write(src_file.read())
target_file.close()
src_file.close()
-
文件对象的常用方法
[外链图片转存中…(img-4pIiYwGE-1679489217515)]
-
with 语句 (上下文管理器)
-
with 语句可以自动管理上下文资源,不论什么原因跳出with块,都能确保文件的正确关闭,以此来达到释放资源的目的
-
原理
[外链图片转存中…(img-GqI2ikmJ-1679489217516)]
-
代码演示
# 语法格式: # with 上下文表达式 as 上下文管理器的引用: # with 语句体 # 上下文表达式:该表达式的结果为一个 上下文管理器,同时会自动调用该上下文管理器的 __enter__()方法,并将返回值赋值给 上下文管理器引用 # 上下文管理器:一个类,实现了 __enter__() 方法和 __exit__() 方法,则这个类遵守了 上下文管理协议,那么这个类就是一个上下文管理器 # 当 with 块执行完后,会自动调用 上下文管理器的 __exit__() 方法 class MyContentManager(object): def __enter__(self): print("enter方法被调用了") # 这里要返回对象,不然会报错:AttributeError: 'NoneType' object has no attribute 'show' # 因为执行到上下文表达式之后,要将该上下文管理器的引用赋值给 as 后的引用 return self def __exit__(self, exc_type, exc_val, exc_tb): # 除self 参数外,还必须要这三个参数 print("exit方法被调用了") def show(self): print("show方法被调用了") with MyContentManager() as file: # 这句相当于是:file = MyContentManager() file.show() # 用 with块实现图片的复制 with open("LaPluma.png", "rb") as src_file: with open("CopyLaPluma2.png", "wb") as target_file: target_file.write(src_file.read())
-
OS 模块
-
os 模块是Python内置的与操作系统功能和文件系统相关的模块。
-
该模块中的语句的执行结果通常与操作系统有关,在不同的操作系统上允许,得到的结果可能不一样
-
os 模块 与 os.path 模块用于对目录或文件进行操作
-
os 模块的常用函数
[外链图片转存中…(img-dmo2JTdH-1679489217516)]
-
os.path 模块 操作目录相关的函数
[外链图片转存中…(img-WMo28VjT-1679489217517)]