目录
常量和表达式
变量
变量命名规则:
硬性规则:
软性规则:
变量类型
整型int
浮点数float
字符串
求字符串长度
字符串的拼接
布尔
变量类型的意义
动态类型特性
注释的使用
输出
输入
算术运算符
除法遇到的问题
除0异常
截断问题
**进行乘方运算
//地板除法(取整除法)
关系运算符
逻辑运算符
赋值运算符
链式赋值:
多元赋值
练习题总结
条件语句
缩进和代码块
条件语句练习
空语句
for循环
人生重开模拟器小游戏
函数
函数形参的默认值
列表和元组
列表的创建和下标访问
列表的切片操作
列表的遍历操作
列表的插入操作
列表的查找和删除
列表的拼接
元组的操作
字典的创建
字典查找key
字典的新增修改删除
理解字典操作的效率
字典的遍历
可哈希的类型
文件
文件路径
打开文件
关闭文件
写文件
读文件
上下文管理器
使用库
代码案例
日期计算器
单词逆序
旋转字符串
统计字符串前缀
文件搜索工具
pip的使用
生成二维码
操作excel
注意:标红处与C/JAVA做区分!!!
常量和表达式
print(2 / 3)
print(1 + 2 / 3)
- 在python中,1 + 2 / 3 = 1.66665,而不是1
编程中,一般没有“四舍五入”这样的规则,IEEE754标准这套规则下,在内存中表示浮点数的时候可能会存在微小的误差,如上面第二行代码
2 / 3 称为表达式,表达式结果称为表达式的返回值,2、3这样的数字称为字面值常量,+、-、*、/称为运算符/操作符
变量
avg = (1 + 2 + 3) / 3
total = (1 - avg) ** 2 + (2 - avg) ** 2 + (3 - avg) ** 2
result = total / 2
print(result)
- 在python中,**2表示平方
变量命名规则:
硬性规则:
1.变量必须由数字、字母、下划线构成,数字不能开头
2.不能和python的“关键字”重复(即在语法中有特殊含义的单词)
3.区分大小写
软性规则:
1.尽量使用描述性的单词,通过名字来表现出变量的作用
2.当有多个单词的时候,命名有规范:
驼峰命名~除了第一个单词的首字母之外,后续每个单词的首字母都大写
蛇形命名~单词之间,使用下划线_来进行分隔
变量类型
整型int
a = 10
print(type(a))
变量类型是由初始化的值的类型决定的,不需要在定义变量的时候显式声明
在python中,int能够表示的数据范围是“无穷”的,可以根据要表示的数据的大小自动扩容
因此,python中不存在long,byte,short这样的类型
浮点数float
b = 0.5
print(type(b))
python中的float就是双精度浮点数,等同于C++/JAVA里面的double
python的一个设计哲学:解决一个问题,只提供一种方案
字符串
引号使用单引号或双引号都可以
c = 'hello'
d = "hello"
print(type(c))
print(type(d))
e = 'My name is "sy"'
print(e)
f = '''My 'name'is "sy"'''
print(f)
也可以使用三引号”’
求字符串长度
d = "hello"
print(len(d))
字符串的拼接
a1 = 'hello'
a2 = 'world'
print(a1 + a2)
不能把字符串和数字混合相加
在python中报错,有两种情况:
1.语法错误,在程序运行之前,python解释器能把错误识别出来
2.运行错误,在程序运行之前识别不了,必须执行到对应的代码才能发现问题
布尔
取值只有两种,True和False(首字母大写),用于逻辑判定
c1 = True
print(type(c1))
变量类型的意义
- 不同类型占用空间不同(int默认4个字节,动态扩容;float固定8个字节;bool一个字节;str变长的)
- 不同类型对应的能够进行的操作也是不同的(str不能-,只能+)
动态类型特性
动态类型:程序运行过程中,变量的类型可能会发生变化;比较灵活,提高语言的表达能力,然而,在编程中,“灵活”这个词往往是“贬义”,更容易出错!相比之下,静态类型的语言还是好一些,尤其是在大型的程序中,多人协作开发
C++/JAVA中是静态类型
a = True
print(type(a))
a = 10
print(type(a))
a的类型随着程序的运行,发生改变
一个编程语言是否是动态类型,只是取决于运行时类型是否发生改变,不取决于变量定义的时候是否声明类型!
python作为一个动态类型的语言,在定义变量的时候,可以写类型,算是锦上添花!
a: int = 10
print(type(a))
注释的使用
批量注释代码:
选中要注释的代码,ctrl+/
# a = True
# print(type(a))
# a: int = 10
- # 行注释
一般写在代码的上方,少数情况写在代码右侧,很少写在代码下方
# 以下代码用来求几个数字的方差
avg = (1 + 2 + 3) / 3
total = (1 - avg) ** 2 + (2 - avg) ** 2 + (3 - avg) ** 2
result = total / 2
print(result)
- 文档字符串
使用三引号引起来的称为“文档字符串”,也可以视为一种注释
可以包含多行内容
一般放在文件/函数/类的开头
“””或者”’均可(等价)
'''
print(type(a))
这是文档字符串
'''
输出
a = 10
# 希望打印出"a=10"这样的内容,数字和字符串混在一起
print(f"a={a}")
print(f"a={a + 10}")
这个语法,叫做“格式化字符串”
f-string此处的f表示”format”
此时可以使用{}
输入
num = input('请输入一个整数:')
print(type(num))
print(f'您输入的数字是{num}')
input返回的值是一个字符串(str)
如果只是单纯拿到用户的输入,然后打印,此时就按照str打印即可
如果需要根据用户输入的内容进行算术计算,此时就需要先把读到的str->int
可以使用int()进行转换
a = input('请输入第一个数字:')
b = input('请输入第一个数字:')
print(f'a+b={a + b}')
直接拼接!而不是算术运算
算术运算(需要进行类型转换):
a = input('请输入第一个数字:')
b = input('请输入第一个数字:')
a = int(a)
b = int(b)
print(f'a+b={a + b}')
把整数转成字符串:str()
算术运算符
除法遇到的问题
除0异常
print(10 / 0)
print('hello')
在python中,0和0.0都不能做除数,运行时出现错误,“抛出异常”——程序直接终止,后面的代码也将不会被执行
有些编程语言中,/0会抛出异常,/0.0(浮点数0)会得到无穷大
而python中都认为是除0异常
截断问题
整数/整数,如果除不尽,得到小数,不会出现截断的情况
**进行乘方运算
既能支持整数次方,也支持小数次方(开方运算)
print(2 ** 0.5)
//地板除法(取整除法)
针对计算的结果进行“向下取整”
print(7 // 3)
print(-7 // 3)
关系运算符
关系运算符对应的表达式,值是布尔类型,表达式符合要求为真,不符合为假
关系运算不光可以针对数字进行比较,还能够比较字符串
比较规则:字典序!依次比较每个字母在英文词典上的顺序
字符串在词典上越靠前就越小,越靠后就越大
a = 'abc'
b = 'abd'
print(a > b)
print(a
针对中文字符串比较大小是没有意义的
C和JAVA中字符串之间不能直接使用==或者!=来比较
C strcmp,如果直接使用==本质上在比较两个字符串首元素地址
JAVA equals方法,如果直接使用==本质上在比较这两个字符串是否是同一个对象
以上都是小众行为
像python直接使用==和!=来比较字符串内容相同是大部分编程语言遵守的语言
针对浮点数来说,使用==比较相等存在一定的风险
因为浮点数在内存中的存储和表示可能存在误差,这样的误差在进行算术运算的时候就可能被放大导致==的判定出现误判!
print(0.1 + 0.2)
print(0.1 + 0.2 == 0.3)
正确比较浮点数是否相等:作差,看差值是否小于预期的误差范围
a = 0.1 + 0.2
b = 0.3
print(-0.000001
python中支持这种连续小于的写法,判定a-b既是-0.000001
逻辑运算符
and,or,not
a
逻辑运算符中的重要细节:短路求值
对于and来说,如果左侧为False,那么整体的值一定是False,右侧表达式不必求值
or同理
a = 1
b = 2
print(a > b and 10 服务器托管网/ 0 == 1)
右侧不再求值,右侧一旦求值,代码是会报错的
a = 1
b = 2
print(a
赋值运算符
链式赋值:
a = b = 20
先把20赋值给b,再把b赋值给a,一般不建议使用
多元赋值
a, b = 1, 2
能够帮助我们解决一些问题,比如交换两个变量
# 使用多元赋值,直接一步到位完成交换
a, b = b, a
python中不支持++、–这样的操作
++a、–a之所以没有报错,是python解释器把++、–当成了正号,但是后置++、–会报错!
练习题总结
- python中的字符串之间能够相加,字符串不能与整数相加,整数和浮点数能够相加,整数和布尔值能够相加(没有意义,Ture表示1,False表示0)
- python中只有字符串类型,没有字符类型,’a’表示长度为1的字符串;正是因为python中没有字符类型,所以”和’都能表示字符串,C++/JAVA有单独的字符类型,所以单引号表示字符,双引号表示字符串
- python中只有float,int,整数表示范围无上限
- int a = 10是典型的错误,如果要表示类型,需要这样做:a:int = 10
- a = 10;在python中,一个语句写完了之后可以加上分号,也可以不加,通常情况下不加,但是如果把多个语句写到同一行了,这时务必加上分号!这种写法并不推荐,影响代码可读性
条件语句
python中的条件语句写法,和很多编程语言不太一样
- if后面的条件表达式,没有()使用,使用:作为结尾
- if/else命中条件后要执行的“语句块”,使用缩进(通常是4个空格或者1个tab)来表示,而不是{}
- 对于多条件分支,不是写作else if,而是elif(合体了)
- python中没有switch,if语句已经可以代替了
choice = input('输入1表示愿意认真学习,输入2表示躺平摆烂:')
# 注意这里要比较的是字符串1,而不是整数1!
if choice == '1':
print('能找到好工作')
elif choice == '2':
print('毕业即失业')
else:
print('输入错误')
缩进和代码块
代码块指的是一组放在一起执行的代码
在python中使用缩进表示代码块,不同级别的缩进,程序的执行效果是不同的
a = input('请输入一个数字:')
if a == '1':
print('aa')
print('bb')
a = input('请输入一个数字:')
if a == '1':
print('aa')
print('bb')
bb和条件无关了,条件是否成立都会打印bb,不属于条件语句
a = input('请输入一个数字:')
if a == '1':
print('aa')
print('bb')
语法上出现问题
a = input('请输入一个数字:')
if a == '1':
print('aa')
print('bb')
python中缩进非常重要,但也不能乱写!
在C++/JAVA中,对于代码缩进是没有强制要求的,缩进具体怎么写都不影响代码的编译运行结果,如果缩进没有好好统一风格,也会影响可读性!
代码解析:两个条件都满足,才会打印a;第一个条件满足,就会打印b,因为打印b的语句只有一级缩进,相当于是if a == ‘1’条件内部的代码块;两个条件都不满足,也能打印c,因为打印c的语句没有缩进,相当于与两个if都无关
当有多级条件嵌套时,当前的语句属于哪个代码块,完全取决于缩进的级别
由于嵌套层次太多,最后两个语句对应哪一级代码块,不容易观察出来,更容易出错
条件语句练习
a = input('请输入一个整数:')
a = int(a) # 类型转换:字符串——>整型
# 等价于:a = int(input('请输入一个整数:'))
if a % 2 == 0:
print('偶数')
else:
print('奇数')
在python中负数余2得到正数0或1,所以以下代码也可以实现:
而在C++/JAVA中不可以:-19%2==-1
a = input('请输入一个整数:')
a = int(a) # 类型转换:字符串——>整型
# a = int(input('请输入一个整数:'))
if a % 2 == 1:
print('奇数')
else:
print('偶数')
空语句
# 输入一个数字,如果数字为1,打印hello
a = input('请输入一个数字:')
if a != '1':
# 啥都不做
else:
print('hello')
没有空语句,报错,需要加上pass(即空语句):
# 输入一个数字,如果数字为1,打印hello
a = input('请输入一个数字:')
if a != '1':
pass
# 啥都不做
else:
print('hello')
for循环
基本语法格式:
for 循环变量 in 可迭代对象:
循环体
注意:
- python中的for和其他语言不同,没有“初始化语句”,“循环条件判定语句”,“循环变量更新语句”,而是更加直接
- 所谓的“可迭代对象”指的是“内部包含多个元素,能一个一个把元素取出来的特殊变量”
代码示例:
for i in range(1, 11):
print(i)
range是一个内建函数,range(beg,end)=>[beg,end)前闭后开区间
range还提供了第三个参数,表示“步长”,默认的步长为1
打印2~10(偶数):
for i in range(2, 12, 2):
print(i)
打印10~1:
for i in range(10, 0, -1):
print(i)
python中没有do while,goto
人生重开模拟器小游戏
import random
import sys
import time
# 人生重开模拟器
print('+-----------------------+')
print('| 花有重开日,人无再少年 |')
print('| |')
print('| 欢迎来到 |')
print('| 人生重开模拟器 |')
print('+-----------------------+')
# 设置初始属性
# 颜值,体质,智力,家境,总和不能超过20,每一项取值都是1~10
while True:
print('请设置初始属性(可用点数为20)')
face = int(input('请输入颜值(1~10):'))
strong = int(input('请输入体质(1~10):'))
iq = int(input('请输入智力(1~10):'))
home = int(input('请输入家境(1~10):'))
# 通过条件语句,对于用户输入的属性做出校验检查
if face 10:
print('输入错误,请重新输入:')
continue
if strong 10:
print('输入错误,请重新输入:')
continue
if iq 10:
print('输入错误,请重新输入:')
continue
if home 10:
print('输入错误,请重新输入:')
continue
if face + strong + iq + home > 20:
print('总的属性超过了20')
continue
print('初始属性输入完毕!')
print(f'颜值:{face},体质:{strong},智力:{iq},家境:{home}')
break
# 生成角色的性别
# 使用random.randint(beg,end),就能生成[beg,end]随机整数
point = random.randint(1, 6) # 在python中,引入其他模块需要先使用import导入
if point % 2 == 0:
gender = 'boy'
print('你是个男孩')
else:
gender = 'girl'
print('你是个女孩')
# 设定角色的出生年份
point = random.randint(1, 3)
if home == 10:
# 第一档
print('你出生在北京,你的父母是高官政要')
home += 1
iq += 1
face += 1
elif 7 = 5:
info += '在父母的悉心照顾下,你康复了'
strong += 1
home -= 1
else:
info += '你的父母没时间管你,你的身体状况更糟糕了'
strong -= 1
elif face = 7:
info += '你长得太丑了,别的的小朋友不喜欢你'
if iq > 5:
info += '你决定用学习填充自己!'
else:
if gender == 'boy':
info += '你和别的的小朋友经常打架'
strong += 1
iq -= 1
else:
info += '你经常被别的小朋友欺负'
strong -= 1
elif iq = 8 and age >= 6:
info += '你的父母把你送到更好的学校学习'
iq += 1
elif 4
函数
- python中,函数必须先定义,再调用
- 形参只要求个数,不要求类型(动态类型)
- 一个函数可以返回多个值,C++/JAVA只能返回一个值
- 如果返回多个值,只需要其中一部分,可以使用_来进行占位!比如:
def getPoint():
x = 10
y = 20
return x, y
a, _ = getPoint() # 只要x的值
x = 10
def test():
global x # 全局
x = 20
test()
print(f'x={x}')# x = 20
没有global,就会把x=20当作是在函数内部创建了一个局部变量,而实际上是要修改全局变量
函数形参的默认值
def add(x, y, debug=False):
if debug:
print(f'x={x},y={y}')
return x + y
result1 = add(10, 20, True)
print(result1)
result2 = add(10, 20)
print(result2)
带有默认值的形参,可以在调用函数的时候,不必传参;让函数的设计更灵活
要求带有默认值的形参,得在形参列表的后面,不能在前面/中间
def test(x, y):
print(f'x={x}')
print(f'y={y}')
test(y=20, x=10)
test(x=10, y=20) # 明确知道参数传给谁,另外可以无视实参、形参位置
test(10, 20)
位置参数和关键字参数能混着用,要求位置参数在前,关键字参数在后
关键字参数一般搭配默认参数使用
列表和元组
变量就是内存空间,用来表示/存储数据
如果表示的数据少,直接定义几个变量即可;有时表示的数据较多,需要用到列表和元组(类似于其他编程语言中的“数组”),这种机制可以用一个变量来表示多个数据
- 列表是一种让程序员在代码中批量表示/保存数据的方式
- 元组和列表相比,非常相似,只是列表中放哪些元素可以修改调整,元组中放的元素是创建元组的时候就设定好的,不能修改调整
列表的创建和下标访问
# 创建列表
# 1.直接使用字面值来创建
# []表示一个空的列表
a = []
print(type(a))
# 2.使用list()来创建
b = list()
print(type(b))
# 3.可以在创建列表的时候,在[]中指定列表的初始值
# 元素之间使用逗号来分割
a = [1, 2, 3, 4]
print(a) # [1, 2, 3, 4]
# 4.可以在同一个列表里放不同类型的变量
a = [1, 'hello', True, [4, 5, 6]]
print(a)
# 5.使用下标来访问列表元素
a = [1, 2, 3, 4]
print(a[2]) # 3
# 6.使用下标来修改列表元素
a = [1, 2, 3, 4]
a[2] = 100
print(a) # [1, 2, 100, 4]
# 7.python中的下标,可以写成负数
# 例如写成-1,其实等价于len(a)-1
# -1就是倒数第一个元素
a = [1, 2, 3, 4]
print(a[len(a) - 1]) # 4
print(a[-1]) # 4
len可以传字符串,列表,元组,字典,自定义的类…——>动态类型
列表的切片操作
通过下标操作一次取出一个元素
通过切片,一次取出一组连续的元素,相当于得到一个子列表
# 1.切片操作的基本使用
a = [1, 2, 3, 4]
print(a[1:3]) # [2, 3]
# 两个数字表示了一段区间,1表示区间开始下标,3表示区间结束下标(前闭后开)[1,3)
# 2.使用切片的时候,省略边界
a = [1, 2, 3, 4]
# 省略后边界,意思是从开始位置,一直取到整个列表结果
print(a[1:]) # [2, 3, 4]
# 省略前边界,意思是从列表的0号元素开始取,一直到结束的后边界
print(a[:2]) # [1, 2]
# 此处切片中的下标也可以写成负数
print(a[:-1]) # [1, 2, 3]
# 把开始边界和结束边界都省略,得到列表本身
print(a[:]) # [1, 2, 3, 4]
切片是一个比较高效的操作,进行切片的时候只是取出了原有列表中的一个部分,并不涉及到数据的拷贝;
假设有一个很大的列表,进行切片,切片的范围也很大,即使如此,切片操作仍然非常高效
切片操作,还可以指定“步长”.range
# 1.切片操作的基本使用
a = [1, 2, 3, 4]
print(a[1:3]) # [2, 3]
# 两个数字表示了一段区间,1表示区间开始下标,3表示区间结束下标(前闭后开)[1,3)
# 2.使用切片的时候,省略边界
a = [1, 2, 3, 4]
# 省略后边界,意思是从开始位置,一直取到整个列表结果
print(a[1:]) # [2, 3, 4]
# 省略前边界,意思是从列表的0号元素开始取,一直到结束的后边界
print(a[:2]) # [1, 2]
# 此处切片中的下标也可以写成负数
print(a[:-1]) # [1, 2, 3]
# 把开始边界和结束边界都省略,得到列表本身
print(a[:]) # [1, 2, 3, 4]
# 3.带有步长的切片操作
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
print(a[::1]) # 1指的是步长,每隔一个元素取一个元素
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
print(a[::2]) # [1, 3, 5, 7, 9]
print(a[1:-1:2]) # [2,4,6,8]
# 4.步长可以是负数,当步长为负数的时候,意为从后往前来取值
print(a[::-1]) # [0, 9, 8, 7, 6, 5, 4, 3, 2, 1]
# 5.当切片中的范围超出有效下标之后,不会出现异常!而是尽可能把符合要求的元素给获取到
a = [1, 2, 3, 4]
print(a[1:100]) # [2, 3, 4]
列表的遍历操作
遍历:把列表/数组/元组中的元素依次取出并进行某种操作
遍历=>搭配循环
# 1.使用for来遍历列表
a = [1, 2, 3, 4]
for elem in a:
print(elem)
# 2.使用for循环遍历,通过下标的方式,并且此方法可以修改里面的值
a = [1, 2, 3, 4]
for i in range(0, len(a)): # 左闭右开
print(a[i])
# 3.使用while循环,通过下标遍历
a = [1, 2, 3, 4]
i = 0
while i
列表的插入操作
# 1.使用append往列表末尾新增一个元素
a = [1, 2, 3, 4]
a.append(5)
a.append('hello')
# 此处的append是搭配列表对象a来一起使用的,而不是作为一个独立的函数
# type,print,input,自定义函数...都是独立的函数
# 这种要搭配对象(变量)来使用的函数,也叫做“方法”(method)
print(a) # [1, 2, 3, 4, 5, 'hello']
b = [5, 6, 7, 8]
b.append('world')
print(b) # [5, 6, 7, 8, 'world']
# 2.还可以使用insert方法,往列表任意位置来新增函数
a = [1, 2, 3, 4]
a.insert(1, 'hello') # 下标为1插入
print(a) # [1, 'hello', 2, 3, 4]
a.insert(100, 'world') # 当超过下标范围,将插在末尾
print(a) # [1, 'hello', 2, 3, 4, 'world']
使用append和insert方法
列表的查找和删除
# 1.使用in来判定某个元素是否在列表中存在
a = [1, 2, 3, 4]
print(1 in a) # True
print(10 in a) # False
print(1 not in a) # False
# 2.使用index方法来判定当前元素在列表中的位置,得到一个下标
a = [1, 2, 3, 4]
print(a.index(2)) # 1 2的下标是1
# print(a.index(10)) # 报错——10 is not in list
# 1.使用pop删除列表中的最末尾的元素
a = [1, 2, 3, 4]
a.pop()
print(a) # [1,2,3]
# 2. 使用pop还能删除任意位置的元素,pop的参数可以传一个下标过去
a = [1, 2, 3, 4]
a.pop(1) # 将下标为1的元素删去,也就是2
print(a) # [1, 3, 4]
# 3.使用remove方法,可以按照值来进行删除
a = ['a', 'b', 'c', 'd']
a.remove('c') # 将'c'删除
print(a) # ['a', 'b', 'd']
列表的拼接
# 1.使用+针对两个列表进行拼接
a = [1, 2, 3]
b = [4, 5, 6]
print(a + b) # [1, 2, 3, 4, 5, 6]
# 使用+来拼接内容,原列表不变
# 2.使用extend来进行拼接
# 将后一个列表内容拼接到前一个列表里面,前一个列表改变,后一个列表不变
a = [1, 2, 3]
b = [4, 5, 6]
c = a.extend(b)
print(a) # [1, 2, 3, 4, 5, 6]
print(b) # [4, 5, 6]
print(c) # None——表示什么都没有,相当于C里面的NULL,或者JAVA里面的null
# extend方法没有返回值
# 倾向于使用extend来完成拼接
# 3.使用+=来进行拼接
a = [1, 2]
b = [3, 4]
a += b
print(a) # [1, 2, 3, 4]
print(b) # [3, 4]
元组的操作
# 1.创建元组
a = ()
print(type(a)) #
b = tuple()
print(type(b)) #
# 2.创建元组的时候,指定初始值
a = [1, 2]
print(a)
# 3.元组中的元素也可以是任意类型的
a = (1, 2, 'hello', True, [])
print(a) # [1, 2, 'hello', True, []]
# 4.通过下标来访问元组中的元素,下标从0开始,到len-1结束
a = (1, 2, 3)
print(a[1]) # 2
print(a[-1]) # 3
# print(a[100]) # 报错——tuple index out of range
# 5.通过切片来获取元组中的一个部分
a = (1, 2, 3)
print(a[1:3]) # (2, 3)
# 6.也同样可以使用for循环等方式来进行遍历元素
a = (1, 2, 3)
for elem in a:
print(elem)
# 7.可以使用in来判断元素是否存在,使用index查找元素的下标
# 8.可以使用+来拼接两个元组
# 9.元组内容不能修改
# 10.当进行多元赋值的时候,其本质上是按照元组的方式来进行工作
def getPoint():
x = 10
y = 20
return x + y
# x, y = getPoint()
print(type(getPoint()))
字典的创建
字典是一种存储键值对的结构
键值对:把键(key)和值(value)进行一个一对一的映射,然后可以根据键快速找到值
在python的字典中,可以同时包含多个键值对,同时这些键不能重复
# 1.创建字典
a = {}
print(type(a)) #
b = dict()
print(type(b)) #
# 2.创建字典的同时设置初始值
a = {'id': 1, 'name': 'zhangsan'}
# 两组键值对
# 'id':1 key就是'id',value就是1
# 'name':'zhangsan' key就是'name',value就是'zhangsan'
# 一个字典中的key类型不一定都一样,value的类型也不必都一样
# 字典对于key是啥类型有约束,对于value是啥类型没约束
# 如果字典中的内容过多,将无法知道有多少键值对,因此,采用以下方法(写成多行形式):
a = {
'id': 1,
'name': 'zhangsan' # 最后一个键值对的逗号可写可不写
}
print(a) # {'id': 1, 'name': 'zhangsan'}
字典查找key
a = {
'id': 1,
'name': 'zhangsan' # 最后一个键值对的逗号可写可不写
}
print(a) # {'id': 1, 'name': 'zhangsan'}
print('id' in a) # True
print('classId' in a) # False
# in只是来判定某个key是否存在,和value无关!
print('zhangsan' in a) # False
# not in来判定key在字典中不存在
print('id' not in a) # False
print('classId' not in a) # True
# 2.使用[]来根据key获取到value
a = {
'id': 1,
'name': 'zhangsan',
100: 'list'
}
print(a['id']) # 1
对于字典来说,使用in或者[ ]来获取value,都是非常高效的操作!
对于列表来说,使用in比较低效(把整个列表遍历),而使用[ ]是比较高效的!
字典的新增修改删除
字典的各种操作,都是针对key来进行的!
# 1.在字典中使用[]来新增元素
a = {
'id': 1,
'name': 'zhangsan'
}
a['score'] = 90
print(a)
# 2.在字典中,根据key修改value,也是使用[]来操作
a['score'] = 100
print(a)
# 3.使用pop方法,根据key来删除键值对
a.pop('name')
print(a)
理解字典操作的效率
遍历:能够把一个可迭代对象里面包含的元素依次取出,并进行一些操作,整个操作不重不漏
字典被设计出来的初衷,不是为了实现遍历,而是为了增删改查
字典是哈希表,进行增删改查,效率都是非常高的!而字典的遍历效率就差一些!
哈希表这个结构很巧妙,能够以“常数级”时间复杂度来完成增删改查,最重要的数据结构!
工作中最常用到的数据结构就是哈希表(没有之一);也是面试中非常高频的问题!
常数级:无论字典中有多少元素,新增、修改、查找、删除都是固定时间,不会因为元素多而操作慢
字典的遍历
keys 获取到字典中所有的key
values 获取到字典中的所有value
items 获取到字典中所有的键值对
a = {
'id': 1,
'name': 'zhangsan',
'score': 90
}
print(a.keys()) # dict_keys(['id', 'name', 'score'])
返回的结果,看起来像列表,又不完全是,自定义的类型
a = {
'id': 1,
'name': 'zhangsan',
'score': 90
}
print(a.values()) # dict_values([1, 'zhangsan', 90])
a = {
'id': 1,
'name': 'zhangsan',
'score': 90
}
print(a.items()) # dict_items([('id', 1), ('name', 'zhangsan'), ('score', 90)])
首先是一个列表一样的结构,里面每个元素又是一个元组,元组里面包含了键和值
a = {
'id': 1,
'name': 'zhangsan',
'score': 90
}
for key, value in a.items():
print(key, value) # 一样完成字典的遍历
可哈希的类型
不是所有的类型都可以作为字典的key
字典本质上是一个哈希表,哈希表的key要求是“可哈希的”,也就是可以计算出一个哈希值
可以使用hash函数计算某个对象的哈希值
但凡能够计算出哈希值的类型,都可以作为字典的key
# 使用hash函数能够计算出一个变量的哈希值
print(hash(0))
print(hash(2))
print(hash(3.14)) # 小数
print(hash('hello')) # 字符串
print(hash(True)) # 布尔值
print(hash((1, 2, 3))) # 元组
# 有的类型不能计算哈希值,比如:
# print(hash([1,2,3]))# 列表 TypeError: unhashable type: 'list'
# print(hash({})) # 字典 TypeError: unhashable type: 'dict'
不可变的对象,一般就是可哈希的;可变的对象,一般就是不可哈希的
列表、字典是可变的
字典、列表、元组是python中非常常用的内置类型,相比于int,str,float…它们内部可以再包含其他元素,可以称得上“容器”或“集合类”
文件
变量是把数据保存到内存中,如果程序重启/主机重启,内存中的数据就会丢失,要想数据持久化存储,就可以把数据存储到硬盘中,也就是在文件中保存
内存、外存区别:
- 内存的空间更小,硬盘空间更大
- 内存访问更快,硬盘访问更慢
- 内存成本更贵,外存成本更便宜
- 内存的数据易失,硬盘的数据持久化存储
硬盘上的数据就是以文件的形式来组织
文件路径
“D:pycharmPyCharm Community Edition 2023.3.3binpycharm64.exe”这样的一段字符串,就是pycharm的路径(文件的路径)——是唯一的
目录名之间,使用来分割,使用/也可以
打开文件
open打开一个文件
# 使用open打开一个文件
f = open('d:/Python环境/test.txt', 'r') # 文件对象
# r表示read,按照读方式打开
# w表示write,按照写方式打开
# a表示append,也是写方式打开,把内容写到原有文件内容的末尾
print(f)
print(type(f))
open的返回值是一个文件对象,此处的文件对象是内存上的一个变量,后续读写操作,都是拿着这个文件对象来进行操作,此处的文件对象就像一个“遥控器”一样
计算机中,也把这样的远程操控的“遥控器”称为“句柄”(handler)
关闭文件
close关闭文件;文件使用完之后,一定要关闭,打开文件其实是在申请一定的系统资源,不再使用文件的时候,资源就应该及时释放,否则造成文件资源泄露,进一步导致其他部分的代码无法顺利打开文件——要有借有还
因为一个系统的资源是有限的,所以程序能打开的文件的个数也是有上限的
# 打开文件个数的上限
flist = []
count = 0
while True:
f = open('d:/Python环境/test.txt', 'r')
flist.append(f)
count += 1
print(f'开开文件的个数:{count}')
结果:
打开文件的个数:8189
在系统中,可以通过一些设置项,来配置能打开文件的最大数目的,但无论配置多少,都不是无穷无尽,需要记得及时关闭,释放资源
8189 + 3 => 8192(2的13次方!)
每个程序在启动的时候,都会默认打开三个文件:
- 标准输入——键盘
- 标准输出——显示器
- 标准错误——显示器
# 打开文件个数的上限
flist = []
count = 0
while True:
f = open('d:/Python环境/test.txt', 'r')
flist.append(f)
f.close()
count += 1
print(f'开开文件的个数:{count}') # 可以显示文件数上限
文件资源泄露,是一个重要的问题,不会第一时间暴露出来,而是在角落里冷不丁偷袭一下
python有一个重要机制,垃圾回收机制(GC),自动地把不适用的变量进行释放
虽然python给了我们后手,让我们在一定程度上避免了上述问题,但是也不能完全依赖自动释放机制!因为自动释放不一定及时,尽量手动释放保证万无一失
写文件
# 使用write来实现写文件的操作
f = open('d:/Python环境/test.txt', 'w')
f.write('hello')
f.close()
# 写文件的时候,需要使用w的方式打开,如果是r方式打开,则会抛出异常
写方式打开,有两种情况,直接写方式打开,追加写方式打开
如果是使用w方式打开,会清空文件原有的内容
f = open('d:/Python环境/test.txt', 'w')
f.close()
如果使用a方式打开,则将在原有内容之上,拼接内容
f = open('d:/Python环境/test.txt', 'a')
f.write('2')
f.close()
如果文件对象已被关闭,那么意味着系统中和该文件相关的内存资源已被释放,强行去写会报错
读文件
# 使用read读取文件内容,指定读几个字符
f = open('d:/python环境/test.txt', 'r', encoding='utf8') # 关键字参数——为了防止报错
# 位置参数和关键字参数可以混着用
result = f.read(2) # 读前两个字符
print(result)
f.close()
更常见的需求,是按行来读取:
最简单的方法,使用for循环:
f = open('d:/Python环境/test,txt', 'r', encoding='utf8')
for line in f:
print(f'line={line}')
f.close()
之所以多了空行,是因为本来读到的文件内容(这一行内容,末尾就有n,此处使用print来打印,又会自动加一个换行符)
可以给print多设定个参数,修改print自动添加换行的行为
f = open('d:/Python环境/test,txt', 'r', encoding='utf8')
for line in f:
print(f'line={line}', end='') # end参数表示每次打印之后要在末尾加个...
f.close()
还可以使用readlines方法直接把整个文件所有内容都读出来,按照行组织到一个列表里
一次读完,速度更快!
f = open('d:/Python环境/test,txt', 'r', encoding='utf8')
lines = f.readlines()
print(lines)
f.close()
上下文管理器
打开文件之后,容易忘记关闭,python提供了上下文管理器,帮助程序员自动关闭文件
使用with语句打开文件,当with内部的代码块执行完毕后,就会自动调用关闭方法
有些情况非常容易遗漏close
万一中间的代码里,有条件判定,函数返回,抛出异常
def func():
f = open('d:/Python环境/test.txt', 'r', encoding='utf8')
# 中间写其他的操作文件的逻辑
# 万一中间的代码里,有条件判定,函数返回,抛出异常
f.close() # 先写
使用上下文管理器可以解决这个问题
def func():
with open('d:/Python环境/test.txt', 'r', encoding='utf8') as f:
#进行文件这里的处理逻辑
if cond:
return
上下文管理器起到的作用,当with对应的代码块执行结束,会自动执行f的close
C++中的智能指针,Java中的try with Resources一样的作用
使用库
库就是别人已经写好的代码,可以直接拿来用
一个编程语言能不能流行起来,一方面取决于语法是否简单方便容易学习,一方面取决于生态是否完备(所谓的“生态”指的是语言是否有足够丰富的库,来应对各种各样的场景)
实际开发中,也并非所有的代码都自己手写,而是要充分利用现成的库,简化开发过程
按照库的来源,可以大致分为两大类:
- 标准库:python自带的库,只要安装了python就可以直接使用Python 标准库 — Python 3.12.2 文档
- 第三方库:其他人实现的库,要想使用,需额外安装(数量更庞大,更丰富)
代码案例
日期计算器
datetime函数
# 构造datetime变量
# import datetime
# date1 = datetime.datetime(2023, 9, 10)
# date2 = datetime.datetime(2024, 3, 3)
# print(date2 - date1) # 175 days, 0:00:00 入学175天
# 或进行以下代码:
# from datetime import datetime
#
# date1 = datetime(year=2023, month=9, day=10) # 不需要再进行.datetime
# date2 = datetime(year=2024, month=3, day=3)
# print(date2 - date1) # 175 days, 0:00:00
# 或进行以下方法:
import datetime as dt
date1 = dt.datetime(2023, 9, 10)
date2 = dt.datetime(2024, 3, 3)
print(date2 - date1) # 175 days, 0:00:00
单词逆序
字符串是python的内置类型,字符串的很多方法不需要导入额外的模块
怎样区分单词?根据空格来分割
在python中的思路:
- 针对上述字符串,使用空格进行切分,字符串split方法可以指定分隔符,把字符串分成多个部分,放到一个list里面
- 针对刚才的切分结果列表,进行逆序
- 把逆序后的列表组合起来~join
def reverseWords(s: str):
tokens = s.split(' ') # 使用空格来区分
tokens.reverse()
return ' '.join(tokens)
print(reverseWords('I am a student')) # student a am I
旋转字符串
把最左侧的字符依次放到最右侧
def rotateString(s, goal):
if len(s) != len(goal):
return False
return goal in (s + s)
print(rotateString('abcd', 'dcba')) # False
print(rotateString('abcd', 'bcda')) # True
print(rotateString('abcd', 'cdab')) # True
print(rotateString('abcd', 'dabc')) # True
统计字符串前缀
遍历words,取出每个字符串,判定当前这个字符串是否是s的前缀即可(s是否是以这个字符串开头的)
startswith方法判断前缀
def countPrefixes(words: list, s: str):
count = 0
for word in words:
s.startswith(word)
if s.startswith(word):
# s是以word开头
count += 1
return count
print(countPrefixes(['a', 'b', 'ab', 'abc'], 'abc')) # 3
print(countPrefixes(['a', 'a'], 'aa')) # 2
文件搜索工具
everything
递归查找:遇到子目录,就进到目录里面进行查找
os.walk使用循环递归遍历目录,不用手写递归服务器托管网代码
dirpath(遍历到当前位置对应的路径是什么), dirnames(当前目录下有哪些目录,这是一个列表,可以包含多个目录), filenames(当前目录下有哪些文件,这是一个列表,可以包含多个文件名)
for dirpath, dirnames, filenames in os.walk(inputPath): os.walk每次调用都能自动针对子目录进行递归操作,只需要使用上述循环就可以把所有的路径都获取出来
# 输入要查找的路径,输入要搜索的文件名(一部分)
# 自动在指定路径中进行查找
import os
inputPath = input('请输入要搜索的路径:')
pattern = input('请输入要搜索的关键词:')
for dirpath, dirnames, filenames in os.walk(inputPath):
print('------------------------------')
print(f'dirpath={dirpath}')
print('dirnames:')
for name in dirnames:
print(name)
print('filenames:')
for name in filenames:
print(name)
# 输入要查找的路径,输入要搜索的文件名(一部分)
# 自动在指定路径中进行查找
import os
inputPath = input('请输入要搜索的路径:')
pattern = input('请输入要搜索的关键词:')
for dirpath, _, filenames in os.walk(inputPath):
for f in filenames:
if pattern in f:
print(f'{dirpath}/{f}')
pip的使用
pip是python内置的包管理器
所谓包管理器就类似于我们平时用的手机app应用商店一样
第三方库很多,是不同的人,不同的组织实现的为了方便大家整理,python官方提供一个网站PyPI The Python Package Index来收集第三方库
安装python的时候已自动将pip安装好,直接使用
使用以下命令,即可安装第三方库:
pip install [库名]
注意:这个命令需要从网络上下载,使用的时候保证网络畅通
安装成功后,即可使用import导入相关模块,即可进行使用
生成二维码
二维码本质上就是一段字符串,生活中使用的二维码,更多的是一个URL(网址)
- 通过搜索引擎,确定使用哪个库
- 查看qrcode文档
import qrcode
img = qrcode.make('未来的程序员,你好')
img.save('qrcode.png') # no news in good news——没有报错,执行成功
我的代码仓库二维码:
操作excel
读取excel可以使用xlrd模块xlrd — xlrd 2.0.1 documentation
修改excel可以使用xlwt模块xlwt documentation — xlwt 1.3.0 documentation
操作excel
- 安装xlrd
pip install xlrd==1.2.0(此处注意要指定版本号安装,如果不指定版本号,则安装最新版,最新版里删除了对xlsx格式文件的支持)
- 编写代码
# 操作excel
import xlrd
# 1.先打开文件
xlsx = xlrd.open_workbook('d:/python环境/test.xlsx')
# 2.获取到指定标签页
table = xlsx.sheet_by_index(0) # 或者标签页的名字(重命名)
# 3.获取到表格中有多少行
nrows = table.nrows
print(f'nrows={nrows}') # nrows=8——excel中有8行
# 4.进行循环统计操作
for i in range(1, nrows): # 表头不算
print('-------------------------')
print(table.cell_value(i, 1)) # 班级
print(table.cell_value(i, 0)) # 姓名
print(table.cell_value(i, 2)) # 分数
统计班级平均分:
# 操作excel
import xlrd
# 1.先打开文件
xlsx = xlrd.open_workbook('d:/python环境/test.xlsx')
# 2.获取到指定标签页
table = xlsx.sheet_by_index(0) # 或者标签页的名字(重命名)
# 3.获取到表格中有多少行
nrows = table.nrows
print(f'nrows={nrows}') # nrows=8——excel中有8行
# 4.进行循环统计操作
total = 0
count = 0
for i in range(1, nrows): # 表头不算
print('-------------------------')
classId = table.cell_value(i, 1) # 班级
if classId == 100: # 100班
total += table.cell_value(i, 2) # 分数总和
count += 1 # 统计人数
print(f'平均分:{total / count}')
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
/** * @param {Function} fn * @return {Function} */ var once = function(fn) { let on = false return function(…args){ if(on){ re服务…