python教程
应用场景:数据处理、网络应用的后端编写、自动化脚本
基础学习:1.python能做什么;2.变量算法解释器、基本数据类型、列表元组字符串字典操作方法;3.条件,循环和相关执行语句(if else elif while for continue bresk 列表推导式 异常处理);4.面向对象OOP,程序结构
、代码重用避免代码冗余打包代码
快捷键:
Alt+Enter 快速修复当前代码,没有import进模块,自动导入模块
ctrl+X 删除整行代码
Ctrl+Alt+L PEP8的代码标准将当前代码格式化
1.输出函数print
# print可以输出数字、字符串、数字表达式;(输出在控制台上)
print(3.14)
print(56)
print('人生苦短,我用python')
print(3+4)
# print将文件输出到文件中;
# 运行几次就输出几次
fe = open('E:/(network)/python资料及练习/test.txt','a+') # a+表示如果文件不存在就创建,存在就在文件内容后面追加
print('hello world!',file = fe)
fe.close()
# print输出内容在一行当中,用逗号,输出以空格相隔
print('hello','world','python')
输出结果:3.14
56
人生苦短,我用python
7
hello world python
注意:print函数的括号里有判断的话返回值为布尔值!
2.转义字符与元字符
# 转义字符:/ 加转义功能的首字母
print('hello/nworld') # 换行--newline
print('hello/tworld') # tab,一个tab键四个空格
print('helloooo/tworld')
print('hello/rworld') # 回车,world将hello覆盖
print('hello/bworld') # 退一格
print('http:////www.baidu.com')
print('她说:’我要学习python‘') #python3支持中文,python2的话这样写:print('她说:’我要学习python‘')
# 元字符,不希望字符串中的转义字符起作用,就使用元字符,在字符串之前加上r,或R
print(r'hello/nworld')
print(r'hello/nworld') # 注意末尾不能加反斜杠/:print(r'hello/nworld/')
输出结果:
hello
world
hello world
helloooo world
world
hellworld
http:/www.baidu.com
她说:’我要学习python‘
hello/nworld
hello/nworld
3.字符编码与4.标识符与保留字
# 字符编码:GBK unicode--utf-8
print(chr(0b100111001011000))
print(ord('乘'))
# 标识符和保留字
import keyword
print(keyword.kwlist) #输出的就为保留字
# 标识符规则:不能以数字、保留字开头,区分大小写;变量、函数、类、模块和其它对象起的名字为标识符
输出结果:
乘
20056
[‘False’, ‘None’, ‘True’, ‘peg_parser‘, ‘and’, ‘as’, ‘assert’, ‘async’, ‘await’, ‘break’, ‘class’, ‘continue’, ‘def’, ‘del’, ‘elif’, ‘else’, ‘except’, ‘finally’, ‘for’, ‘from’, ‘global’, ‘if’, ‘import’, ‘in’, ‘is’, ‘lambda’, ‘nonlocal’, ‘not’, ‘or’, ‘pass’, ‘raise’, ‘return’, ‘try’, ‘while’, ‘with’, ‘yield’]
5.变量的定义与使用
# 变量:内存中一个带标签的盒子;name(变量名)=(赋值运算符)马丽荣(值)
# 变量由三部分组成:ID,type,value;
name = "马丽荣"
print(name)
print('标识:',id(name))
print('类型:',type(name))
print('值:',name)
输出结果:
马丽荣
标识: 2080713636240
类型: <class ‘str’>
值: 马丽荣
6.变量的多次赋值
当变量多次赋值之后,变量名会指向新的空间;
name = '马丽亚'
name = '出溜冰'
print(name)
输出结果:出溜冰
name = '马丽亚'
print(name)
name = '出溜冰'
print(name)
输出结果:
马丽亚
出溜冰
7.数据类型
7.1整形 int
# 可以表示为正数、负数、零;
n1 = 90
n2 = -76
n3 = 0
print(n1,type(n1))
print(n2,type(n2))
print(n3,type(n3))
输出结果:
90 <class ‘int’>
-76 <class ‘int’>
0 <class ‘int’>
# 可以表示为二进制、八进制、十六进制,默认为十进制
print('十进制',118) # 范围0-9
print('八进制',0o176) # 范围0-7 以0o开头
print('十六进制',0x0AF6) # 范围0-9 A-F 以0x开头
print('二进制',0b11111111) # 范围0-1,以0b开头
输出结果:
十进制 118
八进制 126
十六进制 2806
二进制 255
7.2浮点型 float
a = 3.14159
print(a,type(a))
# 使用浮点数进行计算,可能会出现位数不确定的情况
n = 1.1
n1 = 2.2
n2 = 3.3
print(n+n1)
from decimal import Decimal
print(Decimal('1.1')+Decimal('2.2'))
输出结果:
3.14159 <class ‘float’>
3.3000000000000003
3.3
7.3布尔类型 bool (True,Flase)
# 表示真或假的值
f1 = True
f2 = False
print(f1,type(f1))
print(f2,type(f2))
print(f1+1) # 1+1=2,f1为真表示1
print(f2+1) # 0+1=1,f2为假表示0
输出结果:
True <class ‘bool’>
False <class ‘bool’>
2
1
7.4字符串 str
# 称为不可变的字符序列
str = '人生苦短,我用python' #单引号与双引号都可表示一行的字符串
str1 = "人生苦短,我用python"
str2 = '''
人生苦短,我用python1
人生苦短,我用python2
人生苦短,我用python3
''' # 三引号定义的字符串可以分布在连续的多行
print(str,type(str))
print(str1,type(str1))
print(str2,type(str2))
输出结果:
人生苦短,我用python <class ‘str’>
人生苦短,我用python <class ‘str’>
人生苦短,我用python1
人生苦短,我用python2
人生苦短,我用python3
<class ‘str’>
8.数据类型转化
8.1 为什么进行数据转换
# 数据类型转化,将不同的数据类型的数据拼接在一起;
name = '张三'
age = 20
print(type(name),type(age)) # 数据类型不同
# print('我叫'+name+'今年,'+age+'岁') # 报错,类型转化
print('我叫'+name+',今年'+str(age)+'岁') # 加号为连接符
输出结果:
<class ‘str’> <class ‘int’>
我叫张三,今年20岁
8.2 str()函数将其他类型转化成str类型
print('--------------str()函数将其他类型转化成str类型----------')
a = 10
b = 198.9
c = False
print(type(a),type(b),type(c))
print(type(str(a)),type(str(b)),type(str(c)))
输出结果:
————–str()函数将其他类型转化成str类型———-
<class ‘int’> <class ‘float’> <class ‘bool’>
<class ‘str’> <class ‘str’> <class ‘str’>
8.3 int()函数将其他类型转化为int类型
print('-----------int()函数将其他类型转化为int类型--------')
# 文字类与小数类的字符串不能转化为int;浮点数转化为int,末尾为0
s1 = '128'
f1 = 1.595
s2 = '77.889'
ff = True
s3 = 'hello'
print(type(s1),type(f1),type(s2),type(ff),type(s3))
print(int(s1),type(int(s1))) # 将字符串转化为整形,字符串为整数
print(int(f1),type(int(f1))) # 将float转成int类型,截取整数
# print(int(s2),type(int(s2))) # 报错,字符串内为小数串
print(int(ff),type(int(ff)))
# print(int(s3),type(int(s3))) # 字符串内为字母,不能转为int
输出结果:
———–int()函数将其他类型转化为int类型——–
<class ‘str’> <class ‘float’> <class ‘str’> <class ‘bool’> <class ‘str’>
128 <class ‘int’>
1 <class ‘int’>
1 <class ‘int’>
8.4 float()函数将其他类型转化为float型
print('-----------float()函数将其他类型转化为float型------------')
#文字类无法转化为浮点型;整数转成浮点数,末尾为.0
ss1 = 128
ff1 = 1.595
ss2 = '77.889'
fff = False
ss3 = 'hello'
print(type(ss1),type(ff1),type(ss2),type(fff),type(ss3))
print(float(ss1),type(float(ss1)))
print(float(ff1),type(float(ff1)))
print(float(ss2),type(float(ss2)))
print(float(fff),type(float(fff)))
# print(float(ss3),type(float(ss3)))
输出结果:
———–float()函数将其他类型转化为float型————
<class ‘int’> <class ‘float’> <class ‘str’> <class ‘bool’> <class ‘str’>
128.0 <class ‘float’>
1.595 <class ‘float’>
77.889 <class ‘float’>
0.0 <class ‘float’>
python中的注释:中文编码注释–>在文件开头加上中文声明注释,用以指定源码文件的编码格式!
#coding:utf-8 或者 gbk
9.输入函数input()
介绍:接收来自用户的输入;返回类型为str;对输入的值进行存储;
present = input('大圣想要神魔礼物:')
print(present,type(present))
输出结果:
大圣想要神魔礼物:金箍棒
金箍棒 <class ‘str’>
# 练习:输入两个整数,并对其求和;
nu1 = int(input('输入第一2个数:'))
nu2 = int(input('输入第二个数:'))
sum = nu1+nu2
print(sum)
输出结果:
输入第一个数:2
输入第二个数:2
4
10.运算符
10.1 算数运算符
标准算数运算符:
加(+)、减(-)、乘(*)、除(/)、整除(//)
取余运算符:%
幂运算符:**
print(1+1) # 加法运算
print(2-1) # 减法运算
print(2*4) # 乘法运算
print(11/2) # 除法运算
print(6%4) # 取余运算:6除4取余数
print(9//8) # 整除运算:9除8取整商
print(2**3) #幂运算:2的3次方
输出结果:
2
1
8
5.5
2
1
8
算数运算符:
运算符 | 表示 | 例子 | 结果 |
---|---|---|---|
9%4 | 1 | ||
% | 取余一正一负 | 9%-4 | 9-(-4)*(-3)=-3 |
余数=被除数-除数*商 | -9%4 | -9-4*(-3)=3 | |
-9%-4 | -1 | ||
// | 整除(一正一负向下取整) | 9//-4 | -3(2.25=2+1) |
9//4 | 2 | ||
-9//4 | -3 | ||
-9//-4 | 2 |
print(12%8) #4
print(12%-8) # 12-(-8)*(-2)=-4
print(-12%8) # -12-8*(-2)=4
print(-12%-8) # -4
# 输出结果为
4
-4
4
-4
赋值运算符
执行顺序为从右–>左;
支持链式赋值;a=b=c=20
支持参数赋值;+=、-=、*=、//=、%=
a = 10
a += 12 # a=a+12,a=10
print(a)
# 输出结果为:22
支持系列解包赋值;a,b,c,=20,30,40
# 交换两个变量的值
a,b=10,20
print('交换之前:a,b',(a,b))
a,b=b,a
print('交换之后:a,b',(a,b))
输出结果:
交换之前:a,b (10, 20)
交换之后:a,b (20, 10)
比较运算符
对变量或表达式的结果进行大小、真假等比较;
# 运算符:>,<,>=,<=,!=
# == 对象vlaue的比较,
# is,is not 对象的id比较
”==“比较的是值,而“=”是赋值;比较对象的标识使用的是“is”或“is not”
a=10
b=10
print(a==b) # 返回为True,说明a与b的vlaue相等
print(a is b) # 返回为True,说明a与b的标识相等
print(a,id(a))
输出结果:
True
True
10 2242092362320
lis1 = [11,22,33,44]
lis2 = [11,22,33,44]
print(lis1==lis2)
print(lis1 is lis2) # id不同
print(lis1,id(lis1))
print(lis2,id(lis2))
print(lis1 is not lis2)
# 输出结果:
True
False
[11, 22, 33, 44] 2212795138368
[11, 22, 33, 44] 2212795125696
True
比较运算符的结果为布尔类型
a,b = 10,20
print('a>b?',a>b)
输出结果:
a>b? False
布尔运算符
对于布尔值之间的运算;
都有and、or、not in、in;
and:一假则假
a,b = 1,2
print(a==1 and b==2) # True and True 为True
print(a==1 and b<1) # True and Flase 为Flase
print(a!=1 and b==2) # Flase and True 为Flase
print(a!=1 and b<1) # Flase and Flase 为Flase
or:一真则真
print(a==1 or b==2) # True and True 为True
print(a==1 or b<1) # True and Flase 为True
print(a!=1 or b==2) # Flase and True 为FTrue
print(a!=1 or b<1) # Flase and Flase 为Flase
in与not in
f = True
ff = False
print(not f) #对布尔类型操作数进行取反-----Flase
s = 'helloworld'
print('w' in s) # True
print('k' not in s) # True
位运算符
将数据转成二进制计算;
1.位与&:对应位数都是1,结果位数才是1,否则为零
print(4&8) # 按位与&,同为1时结果为1(两个十进制转化为二进制按位计算)
输出结果:0
0000 0100
0000 1000
2.位或|:对应位数都是0,结果位数才是0,否则为1
print(4|8) #按位或|,同为0时结果为0
输出结果:12
0000 0100
0000 1000
0000 1100
3.左移位<<:高位溢出,低位补零(乘以2)
print(4<<1) # 向左移动1位(4乘以2)
输出结果:8
4.右移位>>:高位补零,低位丢弃(移一位除以2—2的幂)
print(4>>2) # 向右移动2位(4除以2**2)
输出结果为:1
补:二进制原码+1=补码
运算符的优先级
算数运算符>位运算>比较运算符>布尔运算>赋值运算;
有括号会先计算括号里的 ;
11.流程控制
11.1程序的组织结构
11.1.1顺序结构:
程序从上到下顺序地执行代码,中间没有任何的判断和跳转,直到程序结束;
对象的布尔值:在python中一切皆对象,所有对象都有一个布尔值,获取对象的布尔值,使用内置函数bool();
print(bool(False))
print(bool(0))
print(bool(0.0))
print(bool(''))
print(bool(None))
print(bool(""))
print(bool([]))
print(bool(list()))
print(bool(()))
print(bool(tuple()))
print(bool({}))
print(bool(dict()))
print(bool(set()))
print('--以上的对象布尔值为False,其余都为True--')
print(bool(18))
print(bool("hello world"))
False、数值0、None、空字符串、空列表、空元组、空字典、空集合的布尔值为False;
11.1.2选择结构(if 语句)
程序根据判断条件的布尔值选择性的执行部分代码,明确的让计算机知道在神魔的条件下,该去做什么;
单分支结构:如果…就
money = 1000
je = int(input('取款金额:'))
if je<=money: # if 条件表达式:(条件表达式为布尔值)
money = money-je
print('取款成功,余额为:',money)
# 输出结果:
取款金额:920
取款成功,余额为: 80
双分支结构:如果不满足…就
语法结构:
if 条件表达式:
条件执行体1
else:
条件执行体2
zs = int(input('输出一个整数:'))
if zs%2==0:
print('此数为偶数!')
else:
print('此数为奇数!')
# 键盘中输入一个数,判断是否为奇数还是偶数;
输出结果:
输出一个整数:100
此数为偶数!
多分支结构:…是…? 是或不是
if 条件表达式1:
条件执行体1
elif 条件表达式2:
条件执行体2
elif 条件表达式N:
条件执行体N
[else:] # 可写可不写
条件执行体N+1
# 从键盘中录入一个“整数”成绩,判断它的范围
# 90-100:A 80-90:B 70-80:C 60-70:及格 60以下不及格
score = int(input('请输入一个整数成绩:'))
if score>=90 and score<=100:# 可以写成90<=score<=100
print('A')
elif score>=80 and score<90:
print('B')
elif score>=70 and score<80:
print('良好')
elif score>=60 and score<70:
print('合格')
elif score<60 and score>=0:
print('不及格')
else:
print('对不起,输入的成绩不在范围之内!')
输出结果:
请输入一个整数成绩:88
B
嵌套if
语法结构:
if 条件表达式1:
if 内层条件表达式:
内层条件执行体1
else:
内层条件执行体2
else:
条件执行体
'''
会员 >=200 8折
>=100 9折
不打折
非会员 >=200 9.5折
不打折
'''
huiyuan = input('是否为会员y/n:')
money = float(input('请输入钱:'))
if huiyuan=='y': # 判断为会员
if money>=200:
print('会员最后金额为:',money*0.8)
elif money>=100:
print('会员最后金额为:',money*0.9)
else:
print('会员最后金额为:',money)
else: # 判断不会为会员
if money>=200: # 大于等于号前后注意空格,空格也有影响;
print('最后非会员金额为:',money*0.95)
else:
print('最后非会员金额为:',money)
# 输出结果:
是否为会员y/n:n
请输入钱:1000
最后非会员金额为: 950.0
从键盘中输入两个数,比较两个数的大小(两种表达方法):
num = float(input('输入第一个数:'))
numm = float(input('输入第二个数:'))
if num>=numm:
print(num,'大于等于',numm)
else:
print(num,'小余等于',numm)
或 条件表达式
num = float(input('输入第一个数:'))
numm = float(input('输入第二个数:'))
print((str(num)+'大于等于'+str(numm)) if num>=numm else (str(num)+'小余等于'+str(numm)))
# 如果if后的条件为True就执行前面的语句,为Flase就执行后面的语句;
条件表达式:是if....else的简写
语法结构:x if 判断条件 else y
运算规则:如果判断条件的布尔值为True,条件表达式的返回值为x,否则条件表达式的返回值为Flase;
pass语句
是:语句什么都不做,只是一个占位符,用在语法上需要语句的地方;
什么时候用:先搭建语法结构,还没想好代码怎么写的时候
与哪些语句一起使用:if 语句的条件执行体、for-in语句循环体、定义函数的函数体
11.1.3循环结构(while 语句与for in)
内置函数range()函数(内置函数:前面不用加任何前缀,可以直接使用的函数):用于生成一个整数序列;将range函数作为循环遍历的对象!
创建range对象的三种方式:
range(stop) 创建一个(0,stop)之间的整数序列,步长为1;
range(start,stop) 创建一个(start,stop)之间的整数序列,步长为1;
range(start,stop,step)
range类型的优点:不管range对象表示的序列有多长,所有range对象占用的内存空间是相同的,因为仅仅需要存储start和step,只有当用到range对象时,才会计算序列中的相关元素;
'''第一种创建方式:只有一个参数(括号里只给一个数)'''
rr = range(10) # 默认从0开始,默认步长为1,不包括10
print(rr) # range(0,10) 返回值是一个迭代对象
print(list(rr)) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 查看range对象中的整数队列
'''第二种创建方式:给了两个参数(括号里给了两个数)'''
rr1 = range(1,10) # 指定了起始值,从1开始,到10结束不包括10,默认步长为1
print(rr1) # range(1, 10)
print(list(rr1)) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
'''第三种创建方式:给三个参数'''
rr2 = range(2,11,2)
print(rr2)
print(list(rr2))
'''判断指定的整数,在序列中是否存在 in 或 not in'''
print(2 in list(rr2))
print(10 not in rr2)
range()函数产生一个整数序列,是一个可迭代对象;
in 与 not in 判断整数序列中是否存在(不存在)指定的指数;
循环结构:
**while **
语法结构:
while 条件表达式:
条件执行体(循环体)
选择结构的if与循环结构while的区别:
if是判断一次,条件为True执行一行;while是判断N+1次,条件为True执行N次;
while循环的执行流程:
四步循环法:初始变量、条件判断、条件执行体(循环体)、改变变量
# 计算0-4之间的累加和
sum = 0
'''初始化变量为0'''
i = 0
while i<=4: # 条件判断
sum = sum + i # 条件执行体(循环体)
i = i+1 # 改变变量
print(sum)
# 计算1-100之间的偶数和
i = 1
sum = 0
while i<=100:
if i%2==0:
sum+=i
i+=1
print(sum)
# 2550
# 计算1-100之间的偶数和
i = 1
sum = 0
while i<=100:
if not bool(i%2): # 为0的布尔值为false,not false=true---执行;1的布尔值为true,not true=false--不执行!
sum+=i
i+=1
print(sum)
for in循环
in表达从(字符串、序列等)中一次取值,又称为遍历;
for in遍历的对象必须是可迭代对象;
语法结构:
for 自定义变量 in 可迭代对象
循环体
for i in range(1,10):
print(i) # 循环的次数
输出结果:
1
2
3
4
5
6
7
8
9
执行了10次,循环次数
for item in "Python":
print(item)
输出结果:
P
y
t
h
o
n
如果在循环体中不需要自定义变量,可将自定义变量写为下划线 “_”;
for _ in range(5):
print('人生苦短,我用python')
输出结果:
人生苦短,我用python
人生苦短,我用python
人生苦短,我用python
人生苦短,我用python
人生苦短,我用python
'''输出100-999之间的水仙花数;
举例:153=3**3+5**3+1**3
'''
for i in range(100,1000):
ge=i%10
shi=i//10%10
bai=i//100
# print(bai,shi,ge)
if ge**3+shi**3+bai**3==i:
print(i)
输出结果:
153
370
371
407
流程控制语句break
break语句用来结束循环结构,通常与分支结构if一起使用;举例用“for in”
# 从键盘录入密码,最多输入三次,如果正确就结束循环;
for i in range(3): # 0 1 2
secret = int(input('请输入密码:'))
if secret==258096:
break
else:
print('密码错误,请重新输入!')
输出结果:
请输入密码:123456
密码错误,请重新输入!
请输入密码:258096
举例用while:
i=1 # 初始化变量
while i<3: # 条件判断
secreat = int(input('请输入密码:')) # 条件执行体
if secreat==123456:
break
else:
print('密码错误,请重新输入')
i+=1 # 改变变量
输出结果:
请输入密码:45689
密码错误,请重新输入
请输入密码:123456
流程控制语句continue
用于结束当前循环,进入下一次循环通常与分支结构中的if一起使用;break是跳出当前循环
# 输入1-50之间的所有的5的倍数
for i in range(1,51):
i*=5
if i>50:
break
else:
print(i)
我写的:嘻嘻
输出结果:
5
10
15
20
25
30
35
40
45
50
注意:在涉及到数字运算时要想到标准算数运算符!
for i in range(1,51):
if not bool(i%5):
print(i)
else:
continue
在视屏的启发下写的:嘻嘻 上面这个是错误的!,按照以下这样写:
for i in range(1,51):
if not bool(i%5):
print(i)
但是必须使用continue,那么就要转化种思路:什么样的数不是5的倍数
for i in range(1,51):-----
if i%5!=0: |
continue----------
print(i)
解释:当i为1时,判断1与5相除取余是否为0,不为0,continue,再到for i in range 循环判断...直到为0输出i
else语句:
与else语句配合使用的三种情况:
第一种情况:
if...:
...
else:
...
第二种情况:
while ...:
...
else:
...
第三种情况:
for ...:
...
else:
...
while 与 for使用在有break或continue时,没有else
for i in range(3):
secret = int(input('请输入密码:'))
if secret==258096:
break
else:
print('密码错误,请重新输入!')
else:
print('对不起,三次密码均输入错误')
输出结果:
请输入密码:123
密码错误,请重新输入!
请输入密码:456
密码错误,请重新输入!
请输入密码:4789
密码错误,请重新输入!
对不起,三次密码均输入错误
i=0
while i<=2:
pwd = int(input('请输入密码'))
if pwd == 123456:
break
else:
print('密码错误')
i+=1
else:
print('对不起,均错误')
请输入密码123
密码错误
请输入密码456
密码错误
请输入密码789
密码错误
对不起,均错误
嵌套循环
循环结构中又嵌套了另外的完整的循环结构,其中内层循环作为外层循环的循环体执行
# 打印三行四列的矩形
'''
****
****
****
'''
for i in range(1,4): # 行数3行
for j in range(1,5): # 列数4列
print('*',end=' ') # 不换行输出
print()
输出结果:
* * * *
* * * *
* * * *
解释:
1 2 3 4 j列
1 * * * *
2 * * * *
3 * * * *
i行
说明:当执行程序第一、二、三行时,i为1--j为1---打印 *
当执行程序第一、二、三行时,i为1--j为2---打印 * *
... * * * *
i为2--j为1---打印 * * * *
*
'''打印九九乘法表,首先试着先把直角三角形打印出来'''
# 打印直角三角形
for i in range(1,10): # 行数
for j in range(1,i+1): # 列数
print(str(i)+'*'+str(j)+'='+str(i * j),end=' ') # 不换行
print() # 换行
解释:
执行第一行时,i=1,
执行第二行时,j在(1,2)取1
执行第三行时,不换行输出第一行、第二行执行结果;为 *
执行第四行时,换行;* 之后换行,进行第二行的打印输出;
i=2 第二行输出
j(1,3)---j=1,j=2 第二行的第一列与第二列
不换行输出--* *
换行输出* *,进行第三行...
输出结果:
1×1=1
2×1=2 2×2=4
3×1=3 3×2=6 3×3=9
4×1=4 4×2=8 4×3=12 4×4=16
5×1=5 5×2=10 5×3=15 5×4=20 5×5=25
6×1=6 6×2=12 6×3=18 6×4=24 6×5=30 6×6=36
7×1=7 7×2=14 7×3=21 7×4=28 7×5=35 7×6=42 7×7=49
8×1=8 8×2=16 8×3=24 8×4=32 8×5=40 8×6=48 8×7=56 8×8=64
9×1=9 9×2=18 9×3=27 9×4=36 9×5=45 9×6=54 9×7=63 9×8=72 9×9=81
二层循环中的break和continue
用于控制本层循环;
break跳出本层循环,不影响后续的程序运行;continue
以下举例没看懂:
for i in range(5): # 循环次数0-4 5次
for j in range(1,11):---------
if j%2==0: |----
break |----内循环,输出的内容
print(j,end=' ')----------
print()
1
1
1
1
1
没看懂在j取(1-10),为什么在这里是1与2!
for i in range(5):
for j in range(1,11):<----
if j%2==0: |
continue----------
print(j,end=' ')
print()
1 3 5 7 9
1 3 5 7 9
1 3 5 7 9
1 3 5 7 9
1 3 5 7 9
总结:循环结构中的while用于次数不固定的循环,初始条件不成立,一次都执行;for in用于遍历可迭代对象;
break结束当前循环结构;continue结束当前循环进入下一次循环;
12 列表
12.1为什么需要列表?
变量可以存储一个元素,而列表可以存储N多个元素,程序可以方便的对这些数据进行整体性操作;列表相当于其他语言中的数组
书包—列表 书本、笔盒…—对象
lst = ['hello','world',89]
print(id(lst))
print(type(lst))
print(lst)
输出结果:
2625645986112
<class 'list'>
['hello', 'world', 89]
解释:
lst 的id是112,类型是列表,value是'hello','world',89
那么,每一个对象也都有id,type,value
12.2列表的创建
'''创建列表的第一种方式---中括号[],元素之间用英文逗号相隔'''
lst = ['hello','world',90]
'''创建列表的第二种方式---使用内置函数list()'''
lst1 = list(['hello','world',90])
解释:内存示意图
-------->|hello(id,type,value)
(id,type,value)lst------->|world(id,type,value)
------->|90(id,type,value)
空列表创建:
lst=[]
lst=list() 与lst=list([]) 输出一样,但id不一样
12.4列表特点
列表元素按顺序有序排序;
索引映射唯一一个数据
索引 -7 -6 -5 -4 -3 -2 -1
数据 'hello' 'world' 123 88.6 'world' 125 world
索引 0 1 2 3 4 5 6
列表可以存储重复数据;
任意数据类型混存;
根据需要动态分配和回收内存
12.5列表的查询–获取列表指定元素的索引
(元素–>索引)
lst = ['hello','world',98,'hello']
# 查询列表中存在N个相同元素,默认只返回相同元素的第一个元素
print(lst.index('hello')) # 输出结果0
# 如果查询的元素在列表中不存在,则会报错
# print(lst.index('99')) # ValueError
# 在指定的start与stop之间寻找
print(lst.index('hello',1,4)) # 1-4 不包括4 输出结果3
12.6获取列表指定的元素
获取列表中的单个元素:索引—->元素
正向索引从0到N-1
逆向索引从-N到-1
指定的索引不存在,IndexError
lst = ['hello','world',98,'hello','wwe',789]
# 获取索引为2的元素
print(lst[2]) # 98
# 获取索引为-3的元素
print(lst[-3]) # hello
# 获取的索引元素超出范围
# print(lst[-10]) # IndexError
获取列表中的多个元素:切片
语法格式:
列表名[start : stop : step]
切片操作:
切片的结果—-原列表切片的拷贝
切片范围:(start : stop) 前包后不包
step 默认为1,简写(start : stop)
step 为正数:
( : stop : step) 切片的第一个元素默认是列表的第一个元素
(start : : step) 切片的最后一个元素默认是列表的最后一个元素
(从start开始往后计算切片)
lst = [10,20,30,40,50,60,70,80,90]
# start=1,stop=6(不包括索引6的元素),step=1
print('原列表',id(lst))
lst1 = lst[1:6:1] # 默认步长为1,lst[1:6:]
print(lst1)
print('切片后:',id(lst1))
print(lst[1:6]) # 默认步长为1
print(lst[1:6:])
print(lst[1:6:2])
print(lst[:6:2])
print(lst[1::2]) # 从索引为1的到列表元素最后
输出结果:
原列表 1878149972288
[20, 30, 40, 50, 60]
切片后: 1878149975552
[20, 30, 40, 50, 60]
[20, 30, 40, 50, 60]
[20, 40, 60]
[10, 30, 50]
[20, 40, 60, 80]
step为负数:
( : stop:step ) 切片的第一个元素默认是列表的最后一个元素
(start ::step) 切片的最后一个元素默认是列表中的第一个元素
(从stop开始往前计算切片)
举例:
lst = [10,20,30,40,50,60,70,80,90]
print('------step为负数-----')
print('原列表',lst)
print(lst[::-1])
print(lst[7::-1])
print(lst[6:0:-2])
输出结果:
------step为负数-----
原列表 [10, 20, 30, 40, 50, 60, 70, 80, 90]
[90, 80, 70, 60, 50, 40, 30, 20, 10]
[80, 70, 60, 50, 40, 30, 20, 10]
[70, 50, 30]
12.7 列表元素的判断及遍历
遍历:将列表中的元素依次输出。
判断指定元素在列表中是否存在—in与not in
元素 in 列表名
元素 not in 列表名
举例:
lst = [10,20,'python','world']
print(10 in lst)
print('hello' not in lst)
输出结果:
True
True
列表元素的遍历:
for 迭代变量 in 列表名: # 目前学习的可迭代对象有列表与字符串。
操作
lst = [10,20,'python','world']
for i in lst:
print(i)
输出结果:
10
20
python
world
12.8列表元素的添加、删除、修改、排序操作
列表元素添加:
append():在列表末尾添加一个元素
# 在列表末尾添加一个元素
lst=[123,'rrt','hello',99]
print('原列表',id(lst))
lst.append(100)
print('添加后的列表',lst,id(lst))
# lst2=['hello','world']
# lst.append(lst2) # 将lst2作为整个列表加在lst里的最后一个元素后面
# print(lst) # [123, 'rrt', 'hello', 99, 100, ['hello', 'world']]
输出结果:
原列表 1503804080448
添加后的列表 [123, 'rrt', 'hello', 99, 100] 1503804080448
[123, 'rrt', 'hello', 99, 100, ['hello', 'world']]
extend():在列表元素末尾以此添加多个元素
# 在列表末尾至少添加一个元素--extend()
lst=[123,'rrt','hello',99,100]
lst2=['hello','world']
lst.extend(lst2) # 将lst2里的元素分别加在lst元素后面
print(lst) # [123, 'rrt', 'hello', 99, 100, 'hello', 'world']
输出结果:
[123, 'rrt', 'hello', 99, 100, 'hello', 'world']
insert():通过索引在列表的任意位置添加一个元素
lst = ['hello','world',99,23,'pwd']
lst.insert(2,'不要学我') # 在指定所以之前添加元素
print(lst)
输出结果:
['hello', 'world', '不要学我', 99, 23, 'pwd']
切片:在列表的任意位置添加至少一个元素
lst=['hello', 'world', '不要学我', 99, 23, 'pwd']
lst2=[True,False,'hello']
lst[3:]=lst2 # 索引为3(包括)切开之后的不要,加上lst2的
print(lst)
输出结果:
['hello', 'world', '不要学我', True, False, 'hello']
列表元素删除:remove()、pop()、切片、del
remove():根据元素删除
一次删除一个指定元素;
lst = [10,20,10,20,50,60,30]
lst.remove(50)
print(lst)
输出结果:
[10, 20, 10, 20, 60, 30]
重复元素只删除第一个;
lst = [10,20,10,20,50,60,30]
lst.remove(20)
print(lst)
输出结果:
[10, 10, 20, 50, 60, 30]
元素不存在的话ValueError
lst = [10,20,10,20,50,60,30]
lst.remove(70)
print(lst)
输出结果:
ValueError: list.remove(x): x not in list
pop():根据索引删除
删除一个指定索引位置上的元素
lst = [10,20,10,20,50,60,30]
lst.pop(0)
print(lst)
输出结果:
[20, 10, 20, 50, 60, 30]
不指定索引,默认删除列表中中最后一个元素
lst = [10,20,10,20,50,60,30]
lst.pop()
print(lst)
输出结果:
[10, 20, 10, 20, 50, 60]
指定索引不存在,ValueError
切片:一次至少删除一个元素,将产生一个新的列表元素
# 删除至少一个元素,产生一个新的列表对象
lst = [10,20,10,20,50,60,30]
new_lst = lst[1:3]
print('原列表',id(lst),lst)
print('新列表',id(new_lst),new_lst)
# 不产生新的列表,而是删除原有列表中的内容
lst[1:3]=[]
print(lst,id(lst))
输出结果:
原列表 2727795245376 [10, 20, 10, 20, 50, 60, 30]
新列表 2727795190080 [20, 10]
[10, 20, 50, 60, 30] 2727795245376
clear():清楚列表中的所有元素
lst = [10,20,10,20,50,60,30]
lst.clear()
print(lst)
输出结果:
[]
del:删除列表
列表元素修改:
为指定索引的元素赋予一个新值(一次修改一个值)
lst = [10,20,10,20,50,60,30]
lst[5]=200
print(lst)
输出结果:
[10, 20, 10, 20, 50, 200, 30]
为指定的切片赋予一个新值(赋予多个新值)
lst = [10,20,10,20,50,60,30]
lst[:4]=[100,200,100]
print(lst)
输出结果:
[100, 200, 100, 50, 60, 30]
列表元素排序:
1.调用sort()方法,列表中的所有元素默认按照从小到大(升序)顺序进行排序,可以指定reverse=True,进行降序排序;
lst = [20,50,98,69,45,60,30]
print('排序前:',lst,id(lst))
lst.sort() # 默认升序,reverse=False
print('排序后:',lst,id(lst))
lst.sort(reverse=True) # 降序
print('再排序后:',lst,id(lst))
输出结果:
排序前: [20, 50, 98, 69, 45, 60, 30] 1996126241088
排序后: [20, 30, 45, 50, 60, 69, 98] 1996126241088
再排序后: [98, 69, 60, 50, 45, 30, 20] 1996126241088
2.调用内置函数sorted()升序,可以指定reverse=True,进行降序排序,原列表不发生变化;(产生一个新的列表对象)
lst = [20,50,98,69,45,60,30]
print('排序前:',lst,id(lst))
lst1=sorted(lst) # 默认升序,reverse=False
print('排序后:',lst1,id(lst1))
jixu=sorted(lst,reverse=True) # 降序
print('再排序后:',jixu,id(jixu))
输出结果:
排序前: [20, 50, 98, 69, 45, 60, 30] 2350573895936
排序后: [20, 30, 45, 50, 60, 69, 98] 2350576623040
再排序后: [98, 69, 60, 50, 45, 30, 20] 2350573896512
12.9列表生成式–生成列表的公式
语法格式:
[i*i for i in range(1,10)]
i*i 表示列表元素的表达式;
i 自定义变量
range(1,10) 可迭代对象
# 注意事项:“表示列表元素的表达式”中通常包含自定义变量
举例:
lst = [i for i in range(1,10)] # 将1-9的序列赋值给i,在以列表的格式输出
print(lst)
输出结果:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
输入2 4 6 8 10的列表
lst = [i*2 for i in range(1,6)] # 将1-9的序列赋值给i,在以列表的格式输出
print(lst)
输出结果:
[2, 4, 6, 8, 10]
13 字典
13.1什么是字典?
是python内置的数据结构之一,与列表一样是一个可变序列(数据结构可执行增删改操作);不可变序列:整数、字符串(不进行增删改操作)
以键值对的方式存储数据,字典是一个无序的序列;键不可重复。
13.2字典的原理
实现原理:数据在字典中存储的时候会进行哈希算法,将key进行哈希计算存储位置,所以key必须是一个不可变序列,根据key查找value所在的位置
13.3字典的创建
1.使用花括号{}
score = {'张三':100,'李四':98,'王五':45}
空字典:
dcc = {}
2.使用内置函数dict()
dic(name='jack',age=20)
13.4字典的查询操作
字典中元素的获取:根据键获取值
1.[] 举例:score['张三']
2.get()方法 举例:score.get('张三',66)# 如果张三不存在则返回默认值66
二者取值的区别:
[]如果字典中不存在指定的key,抛出keyError异常
get()方法取值,如果字典中不存在指定的key,并不会抛出KeyError,而是返回None,可以通过参数设置默认的value,以便指定的key不存在返回
key值判断:
in 指定的key在字典中存在返回True;
not in 指定的key在字典中不存在返回True
score = {'张三':100,'李四':98,'王五':45}
print('张三' in score)
print('张三' not in score)
输出结果:
True
False
获取字典视图的三种方法:
1.keys()—-获取字典中所有的key
score = {'张三':100,'李四':98,'王五':45}
key = score.keys()
print(key)
print(type(key))
print(list(key))
输出结果:
dict_keys(['张三', '李四', '王五'])
<class 'dict_keys'>
['张三', '李四', '王五']
2.values()—–获取字典中所有的value
score = {'张三':100,'李四':98,'王五':45}
value = score.values()
print(value)
print(type(value))
输出结果:
dict_values([100, 98, 45])
<class 'dict_values'>
3.items()——获取字典中所有的key,value对
score = {'张三':100,'李四':98,'王五':45}
ii = score.items()
print(ii)
print(type(ii))
输出结果:
dict_items([('张三', 100), ('李四', 98), ('王五', 45)])
<class 'dict_items'>
字典元素的遍历:
for item in score:# 获取的是键,其中item是自定义变量
print(item)
score = {'张三':100,'李四':98,'王五':45}
for item in score:
print(item) # 获取的是键
输出结果:
张三
李四
王五
score = {'张三':96,'李四':100,'麻七':100}
for item in score:
# print(item)
# print(score[item]) 根据key获取vlaue
print(score.get(item))
输出结果:
96
100
100
13.5字典元素的增删改操作
字典元素的删除:
del score[‘张三’]
score.clear() # 清空字典中的元素 {}
score = {'张三':100,'李四':98,'王五':45}
del score['张三'] # 删除指定的键值对
print(score)
输出结果:
{'李四': 98, '王五': 45}
字典元素的新增:
score[‘jack’]=90
也可以修改元素的值:score[‘李四’]=60
score = {'张三':100,'李四':98,'王五':45}
score['小二'] = 90
print(score)
输出结果:
{'张三': 100, '李四': 98, '王五': 45, '小二': 90}
字典的特点:
1.字典中的所有元素都是一个key-value对,key不可以重复,value可以重复;
2.字典中的元素是无序的;
3.字典中的key必须是不可变对象;
4.字典也可以根据需要动态地伸缩
5.字典会浪费较大的内存,是一种使用空间换时间的数据结构
13.6字典推导式
字典生成式:
内置函数zip():用于将可迭代的对象(可以使用for in循环遍历的对象)作为参数,将对象中对应的元素打包成一个元组,然后返回由这些元组组成的列表
items = ['Fruits','Book','Other']
prices = [96,78,85]
zz = zip(items,prices)
print(list(zz))
输出结果:
[('Fruits', 96), ('Book', 78), ('Other', 85)]
tool = ['Fruits','Book','Others']
prace = [98,56,78]
di={kes:vaus for kes,vaus in zip(tool,prace)}
print(di)
输出结果:
{'Fruits': 98, 'Book': 56, 'Others': 78}
items = ['Fruits','Book','Other']
prices = [96,78,85]
pz={items.upper():prices for items,prices in zip(items,prices)}
# 解释:
items.upper():prices
items,prices
zip(items,prices)
print(pz)
输出结果:
{'FRUITS': 96, 'BOOK': 78, 'OTHER': 85}
14 元组
14.1 元组介绍
python内置的数据结构之一,是一个不可变序列;
不可变序列与可变序列:
不可变序列:字符串、元组(没有增删改操作)
'''不可变序列:字符串,元组...内存地址在增删改之后发生变化'''
s = '哈哈'
s1 = s+'hello'
print(s,id(s)) # 2426108766224
print(s1,id(s1)) # 2426108766416
输出结果:
哈哈 2426108766224
哈哈hello 2426108766416
可变序列:列表、字典(可以对序列执行增删改操作,对象地址不发生更改)
'''可变序列:列表,字典...内存地址在增删改之后没发生变化'''
lst = [50,'hello',56,80]
print(lst,id(lst)) # 1847814275392
lst.append(99)
print(lst,id(lst)) # 1847814275392
输出结果:
[50, 'hello', 56, 80] 1847814275392
[50, 'hello', 56, 80, 99] 1847814275392
14.2元组的创建方式:
tup = ('python','world',90)
print(tup,type(tup))
tup1 = tuple(('python','world',90))
print(tup1,type(tup1))
输出结果:
('python', 'world', 90) <class 'tuple'>
('python', 'world', 90) <class 'tuple'>
# 注意
tup = ('python','world',90) # 也可以写成tup='python','world',90
如果是一个元素,比如:tt = ('poop'),输出的类型是str,所以“只包含一个元组的元素需要使用逗号和小括号” ,逗号不能省略!!!
tt=('poop')
print(tt,type(tt)) # poop <class 'str'>
tt=('poop',)
print(tt,type(tt)) # ('poop',) <class 'tuple'>
# 创建空元组
tt=()
tt=tuple()
# 创建空字典
dd={}
dd=dic()
14.2元组的遍历
元组是可迭代对象,所以可以使用for…in进行遍历(走一遍)
ttp=('python',980,'world')
print(ttp[0]) # 获取元组方式
for i in ttp:
print(i)
输出结果:
python
python
980
world
15 集合
15.1 集合的概述与创建:
集合是什么:
Python语言提供的内置数据结构;
与列表、字典一样都属于可变类型(增删改查)的序列;
集合是没有value的字典;
向集合里放数据元素会通过哈希函数计算存储位置,所以第一个放进的元素未必在第一位。(集合元素是无序的)
集合的创建方式:
1.直接{} s={‘python’,’hello’,90},存储单个元素,不允许重复.
s={6,6,7,4,5,6,4,3,4,3} # 将重复元素去掉
print(s)
输出结果:
{3, 4, 5, 6, 7}
2.使用内置函数
s = set(range(6))
print(s) # {0, 1, 2, 3, 4, 5}
s = set([2,5,6,2,4,6,3,2])
print(s,type(s)) # {2, 3, 4, 5, 6} <class 'set'>
s = set((34,6,78,90))
print(s,type(s)) # {78, 34, 90, 6} <class 'set'>
s = set('python')
print(s,type(s)) # {'y', 'o', 'p', 'n', 'h', 't'} <class 'set'>
s = set({34,56,78,11,22,22})
print(s,type(s)) # {34, 22, 56, 11, 78} <class 'set'>
s = set() # 定义一个空集合,如果是s={}的话数据类型是字典!
print(s,type(s)) # set() <class 'set'>
15.2 集合的相关操作:
集合元素的判断操作:in或not in
s = {1,2,5,9,80,100}
print(1 in s)
print(100 not in s)
True
False
集合元素的新增操作:
1.调用add()方法,一次添加一个元素
2.调用update()方法至少添加一个元素
s = {1,2,5,9,80,100}
s.add(12)
print(s) # {1, 2, 100, 5, 9, 12, 80}
s = {1,2,5,9,80,100}
s.update({300,20,800,70})
print(s) # {800, 1, 2, 100, 5, 70, 9, 300, 80, 20}
s = {1,2,5,9,80,100}
s.update(['op',78,66])
print(s) # {1, 2, 'op', 100, 5, 66, 9, 78, 80}
s = {1,2,5,9,80,100}
s.update((65,88,99,'oh'))
print(s) # {1, 2, 65, 100, 5, 99, 9, 80, 88, 'oh'}
集合元素的删除操作:
调用remove()方法,一次删除一个指定的元素,如果指定的元素不存在抛出keyerror;
s = {1,2,5,9,80,100}
s.remove(100)
print(s) # {1, 2, 5, 9, 80}
s = {1,2,5,9,80,100}
s.remove(90)
print(s) # KeyError
调用discard()方法,一次删除一个指定的元素,如果指定的元素不存在不抛出异常;
s = {1,2,5,9,80,100}
s.discard(90)
print(s) # {1, 2, 100, 5, 9, 80} 有就删除,没有不报错
调用pop()方法,一次只删除一个任意的元素;
s = {1,2,5,9,80,100,11}
s.pop() # 不能添加参数,规定无参;TypeError
print(s) # {2, 100, 5, 9, 11, 80}
调用clear()方法,清空集合;
s = {1,2,5,9,80,100,11}
s.clear() #无参,清空
print(s) # set()
15.3 集合间的关系
两个集合是否相等:可以使用运算符==或!=进行判断
s1={10,20,30,40}
s2={40,30,10,20}
print(s1==s2) # True
print(s1!=s2) # False
集合里的元素是无序列,输出的顺序不会决定存储顺序(元素内容相同集合即可)
一个集合是否是另一个集合的子集:可以调用方法issubset进行判断;B是A的子集
s1={10,20,30,40}
s2={40,30,10,20,60,100}
s3={10,20,30,90,100}
se=s1.issubset(s2)
see=s3.issubset(s1)
print(se) # True
print(see) # False
一个集合是否是另一个集合的超集:可以调用方法issuperset进行判断;A是B的超级
s1={10,20,30,40}
s2={40,30,10,20,60,100}
s3={10,20,30,90,100}
se=s2.issuperset(s1)
see=s2.issuperset(s3)
print(se) # True
print(see) # False
两个集合是否没有交集:可以调用方法isdisjoint进行判断
s1={10,20,30,40}
s2={40,30,10,20,60,100}
s3={400,500,45}
se=s2.isdisjoint(s1)
see=s2.isdisjoint(s3)
print(se) # Flase 有交集为flase
print(see) # True 无交集为True
15.4 集合的数据操作
集合的数学关系:
交集:
s1={50,45,89,40,10}
s2={40,89,50,10,30}
print(s1.intersection(s2))
print(s1 & s2) # intersection()与&都是交集操作
输出结果:
{40, 89, 10, 50}
{40, 89, 10, 50}
并集:
s1={50,45,89,40,10}
s2={40,89,50,10,3099,66}
print(s1.union(s2))
print(s1 | s2) # union()与|都是并集操作
输出结果:
{66, 40, 10, 45, 50, 89, 3099}
{66, 40, 10, 45, 50, 89, 3099}
差集:
s1={50,45,89,40,10}
s2={40,89,50,10,3099,66}
print(s1.difference(s2)) # s1-s2 {45}
print(s2.difference(s1)) # s2-s1 {66, 3099} 在s2的集合里将s1的元素全部去掉
print(s1 - s2) # difference()与-都是差集操作
输出结果:
{45}
{45}
对称差集:
s1={50,45,89,40,10}
s2={40,89,50,10,3099,66}
print(s1.symmetric_difference(s2)) # 去掉相同的元素,余留下来的元素
print(s1 ^ s2) # symmetric_difference()与^都是对称差集操作
输出结果:
{66, 3099, 45}
{66, 3099, 45}
15.5 集合生成式
用于生成集合的公式:
{i*i for i in range(10)}
i*i表示集合元素的表达式
i自定义变量
range(10)可迭代对象(迭代:轮流代替)、
将{}修改为[]就是列表生产式
没有元组生成式,因为元组是不可变数据类型;
sett = {i*i for i in range(10)} # for i in range(10) 默认0-9
print(sett) # 集合元素是无序的
输出结果:
{0, 1, 64, 4, 36, 9, 16, 49, 8125}
列表、字典、元组、集合总结
数据类型 | 是否可变 | 是否重复 | 是否有序 | 定义符号 |
---|---|---|---|---|
列表(list) | 可变 | 可以重复 | 有序 | [] |
元组(tuple) | 可变 | 可以重复 | 有序 | () |
字典 | 可变 | key不可重复;value可重复 | 无序 | {key:”value”} |
集合 | 可变 | 不可重复 | 无序 | {} |
16 字符串
16.1 字符串的驻留机制
字符串:在python中字符串是基本数据类型,是一个不可变的字符序列;
a='python'
aa="python"
aaa='''python'''
print(a,id(a))
print(a,id(aa))
print(a,id(aaa))
输出结果:
python 1481882442352
python 1481882442352
python 1481882442352
解释:
创建aa字符串的时候,发现存储中有相同的字符串,不会再开辟新的存储空间,而是把该字符的地址付给新创建的变量。
字符串的驻留机制:仅保存一份相同的且不可变的字符串方法,不同的值被存放在字符串的驻留池中,python的驻留机制对相同的字符串只保存一份拷贝,后续创建相同字符串时,不会开辟新空间,而是把该字符的地址赋给新创建的变量。
驻留机制的几种情况(交互模式):
字符串的长度为0或1时;
>>> s1='' # 字符长度为0
>>> s2=''
>>> s1 is s2
True
>>> s1='%' # 字符长度为1
>>> s2='%'
>>> s1 is s2
True
符合标识符的字符串(字母,数字,下滑线);
>>> s1='abc%' # 不符合字符串
>>> s2='abc%'
>>> s1==s2
True
>>> s1 is s2
False
>>> id(s1)
2277190557360 ----------- 内存地址不一样!
>>> id(s2)
2277190557424 -----------
>>> s1='abcx'
>>> s2='abcx'
>>> s1==s2
True
>>> s1 is s2 ---------内存地址一样!
True
字符串只在编译时进行驻留,而非运行时;
>>> a='abc'
>>> b='ab'+'c' # b的值在连接之前就完成了
>>> c=''.join(['ab','c']) # c是程序运行的时候对列表中的数据进行连接的
>>> a is b
True
>>> a is c
False ----------------注意这里!!!
>>> c
'abc'
>>> type(c)
<class 'str'>
>>> type(a)
<class 'str'>
[-5,256]之间的整数数字;
>>> a=-5
>>> b=-5
>>> a is b
True
>>> a=-6
>>> b=-6
>>> a is b
False
sys中的inter方法强制2个字符串指向同一个对象;
>>> import sys
>>> a='abc%'
>>> b='abc%'
>>> a is b
False
>>> a=sys.intern(b)
>>> a is b
True
pycharm对字符串进行了优化处理;
字符串驻留机制的优缺点:
当需要值相同的字符串时可以直接从字符串池里拿来使用,避免频繁的创建和销毁,提升雄安率和节约内存,因此拼接字符串和修改字符串是会比较影响性能的;
在需要进行字符串拼接时建议使用str类型的join方法,而非+join()方法是先计算出所有字符串的长度,然后再拷贝,只new一次对象,效率要比“+”效率高。
16.2 字符串的常用操作
查询操作方法:
功能 | 方法名称 | 作用 |
---|---|---|
查询方法 | index() | 查找子串substr第一次出现的位置,如果查找的子串不存在时,则抛出ValueError |
rindex() | 查找子串substr最后出现的位置,如果查找的子串不存在时,则抛出valueerror | |
find() | 查找子串substr第一次出现的位置,如果查找的子串不存在时,则返回-1 | |
rfind() | 查找子串substr最后出现的位置,如果查找的子串不存在时,则返回-1 |
两者的区别就是:找不到出现的位置时,报错结果不一样;
s='hello,hello'
print(s.index('lo'))
print(s.rindex('lo')) # 逗号也是一个索引值
输出结果:
3
9
s='hello,hello'
print(s.find('p'))
print(s.rfind('lo'))
输出结果:
-1
9
解释:
大小写转换操作的方法:
功能 | 方法名称 | 作用 |
---|---|---|
大小写转化 | upper() | 把字符串中所有字符都转成大写字母 |
lower() | 把字符串中所有字符都转成小写字母 | |
swapcase() | 把字符串中所有大写字母转换成小写字母,把所有小写字母转换成大写字母 | |
capitalize() | 把第一个字符转换成大写,把其余字符转换为小写 | |
title() | 把每个单词的第一个字符转换为大写,把每个单词的剩余字符转换为小写 |
s='hello,python'
a=s.upper()
print(a,id(a))
print(s,id(s))
输出函数:
HELLO,PYTHON 1845603946160
hello,python 1845603572336
解释:字符串是不可变数据类型,转换成大写内存位置不一样,开辟了另一个存储空间,产生新的字符串对象。
s='hello,python'
a=s.lower() # 转换之后会产生一个新的字符串对象
print(a,id(a))
print(s,id(s))
print(a==s)
print(a is s) # 内存位置不一致;
输出结果:
hello,python 2168620011248
hello,python 2168619974384
True
False
s2='hello,Python'
print(s2.swapcase()) # HELLO,pYTHON
print(s2.title()) # Hello,Python
print(s2.capitalize()) # Hello,python
内容对齐操作的方法:
功能 | 方法名称 | 作用 |
---|---|---|
字符串对齐 | center() | 居中对齐,第一个参数指定宽度,第二个参数指定填充符,第2个参数是可选的,默认是空格,如果设置宽度小于实际宽度则返回原字符串 |
ljust | 左对齐,第一个参数指定宽度,第二个参数指定填充符,第二个参数是可选的,默认是空格,如果设置宽度小于实际宽度则返回原字符串 | |
rjust | 右对齐,第一个参数指定宽度,第二个参数指定填充符,第二个参数是可选的,默认是空格,如果设置宽度小于实际宽度则返回原字符串 | |
zfill() | 右对齐,左边用0填充,该方法只接受一个参数,用于指定字符串的宽度,如果指定的宽度小于等于字符串的长度,返回字符串本身。 |
s='hello,python'
print(s.center(20,'*')) # ****hello,python****
print(s.ljust(20,"*")) # hello,python********
print(s.center(10,'*')) # hello,python
print(s.center(20))
输出结果:
****hello,python****
hello,python********
hello,python
hello,python
print(s.rjust(20,'*'))
print(s.rjust(20))
print(s.ljust(10,'*'))
输出结果:
********hello,python
hello,python
hello,python
print(s.zfill(20))
print(s.zfill(10))
print('-8901'.zfill(8))
输出结果:
00000000hello,python
hello,python
-0008901
劈分操作的方法:
功能 | 方法名称 | 作用 |
---|---|---|
字符串的劈分 | split() | 从字符串的左边开始劈分,默认的劈分字符串是空格字符串,返回的值都是一个列表 |
以通过参数sep指定劈分字符串的是劈分符 | ||
通过参数maxsplit指定劈分字符串时的最大劈分次数,在经过最大次劈分之后,剩余的字串会单独做为一部分 | ||
rsplit() | 从字符串的右边开始劈分,默认的劈分字符是空格字符串,返回的值都是一个列表 | |
以通过参数sep指定劈分字符串的是劈分符 | ||
通过参数maxsplit指定劈分字符串时的最大劈分次数,在经过最大次劈分之后,剩余的字串会单独做为一部分 | ||
strip() 方法 | 用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列 |
s='hello world Python'
lst=s.split()
print(lst)
输出结果:
['hello', 'world', 'Python']
s1='hello|world|python'
lst1=s1.split(sep='|')
print(lst1)
输出结果:
['hello', 'world', 'Python']
s1='hello|world|python'
lst1=s1.split(sep='|',maxsplit=1)
print(lst1)
输出结果:
['hello', 'world|python']
s='hello world Python'
lst=s.rsplit()
print(lst)
输出结果:
['hello', 'world', 'Python']
s1='hello|world|python'
lst1=s1.rsplit('|')
print(lst1)
输出结果:
['hello', 'world', 'python']
s1='hello|world|python'
lst1=s1.rsplit(sep='|',maxsplit=1)
print(lst1)
输出结果:
['hello|world', 'python']
判断字符串操作的方法
功能 | 方法名称 | 作用 |
---|---|---|
判断字符串的方法 | isidentifier() | 判断指定的字符串是不是合法的标识符 |
isspace() | 判断指定的字符串是否全部由空白字符组成(回车、换行、水平制表符) | |
isalpha() | 判断指定的字符串是否全部由字母组成 | |
isdecimal() | 判断指定字符串是否全部由十进制的数字组成 | |
isnumeric() | 判断指定的字符串是否全部由数字组成 | |
isalnum() | 判断指定的字符串是否全部由字母和数字组成 |
s='hello,python'
print(s.isidentifier()) # False
print( 'hello'.isidentifier()) # True
print('张三_'.isidentifier()) # True
print('张三_123'.isidentifier()) # True
print('/t'.isspace()) # True
print('abc'.isalpha()) # True
print('张三'.isalpha()) # True
print('张三1'.isalpha()) # Flase
print('123'.isdecimal()) # True
print('123四'.isdecimal()) # Flase
print('ⅡⅡⅡ'.isdecimal()) # Flase
print('123'.isnumeric()) # True
print('123四'.isnumeric()) # True
print('ⅡⅡⅡ'.isnumeric()) # True
print('abc1'.isalnum()) # True
print('张三123'.isalnum()) # True
print('abc!'.isalnum()) # False
字符串操作的其它方法
功能 | 方法名称 | 作用 |
---|---|---|
字符串替换 | replace() | 第一个参数指定被替换的子串,第二个参数指定替换子串的字符串,该方法返回替换后得到的字符串,替换前的字符串不发生变化,调用该方法时可以通过第三个参数指定最大替换次数 |
字符串的合并 | join() | 将列表或元组中的字符串合并成一个字符串 |
s='hello,Python'
print(s.replace('Python','java'))
s1='hello,Python,Python,Python'
print(s1.replace('Python','java'))
print(s1.replace('Python','java',2))
输出结果:
hello,java
hello,java,java,java
hello,java,java,Python
lst=['hello','java','python']
print('|'.join(lst))
输出结果:
hello|java|python
lst=['hello','java','python'] -----列表
print(' '.join(lst))
输出结果:
hello java python
tup=('hello','java','python') -------元组
print(' '.join(tup))
输出结果:
hello java python
print('*'.join('python'))
输出结果:
p*y*t*h*o*n
16.3 字符串的比较
字符串的比较操作:
运算符:>,<=,<,<=,==,!=
比较规则:首先比较两个字符串中的第一个字符,如果相等则继续比较下一个字符,以此比较下去,直到两个字符串中的字符不相等时,其比较结果就是两个字符串的比较结果,两个字符串中的所有后续字符将不再被比较;
比较原理:两个以上字符进行比较时,比较的是其ordinal value(原始值),调用内置函数ord可以得到指定字符的ordinal value。与内置函数ord对应的是内置函数chr,调用内置函数chr时指定ordinal value可以得到其对应的字符。
print('apple'>'app') # True
print('apple'>'banana') # False
print(ord('a'),ord('b')) # 获取字符的原始值 97 98
print(ord('马')) # 39532
print(chr(97),chr(98)) # 获得原始值所对应的字符 a b
print(chr(39532)) # 马
== 比较的是value;is比较的是id(内存地址)是否相等
a=b='python'
c='python'
print(a==b) # True
print(b==c) # True
print(a==c) # True
print(a is b) # True
print(a is c) # True
print(b is c) # True
print(id(a)) # True 1920823049840
print(id(c)) # True 1920823049840
print(id(a)) # True 1920823049840
16.4 字符串的切片操作
字符串是不可变类型,不具备增删改操作,切片操作将产生新的对象
切片:
[start:end:step] 步长是以索引为单位的
s='hello,python'
s1=s[:5] # 由于没有指定起始位置,默认从索引值0
s2=s[6:]
s3='!'
ss=s1+s3+s2
print(s1)
print(s2)
print(ss)
print(id(s1),type(s1))
print(id(s2),type(s2))
print(id(s3),type(s3))
print(id(ss),type(ss))
输出结果:
hello
python
hello!python
2858431575024 <class 'str'>
2858431575088 <class 'str'>
2858431526000 <class 'str'>
2858431575152 <class 'str'>
s='hello,python'
print(s[1:5:1]) # ello 从索引为1开始到索引为5,不包含索引为5的,步长为1;
print(s[::2]) # 索引为0,2,4,6,8,10
# hlopto
print(s[::-1]) # 输出:nohtyp,olleh
# 默认从从字符串的最后一个元素开始,到字符串的第一个元素
print(s[-6::1]) # python
16.5 格式化字符串
字符串的拼接格式
两种方式:
%作占位符,%s:字符串,%i或%d:整数,%f:浮点数。
# %做占位符
name='张三'
age=3
print('我叫%s,今年%d岁' % (name,age))
输出结果:
我叫张三,今年3岁
{}作占位符,
# {}做占位符
name='张三'
age=3
print(f'我叫{name},今年{age}岁')
# f-string格式
print('我叫{0},今年{1}岁'.format(name,age))
输出结果:
我叫张三,今年3岁
我叫张三,今年3岁
表示的精度和宽度
print('%10d' % 66) # 10 表示的是宽度
输出结果:
66
print('%f' % 3.1415926)
print('%.3f' % 3.1415926)
print('%10.3f' % 3.1415926) # 宽度为10,精度为小数点后3位
输出结果:
3.141593
3.142
3.142
print('{0}'.format(3.1415926))
输出结果:
3.1415926
print('{0:.3}'.format(3.1415926)) # 表示总共3位数
输出结果:
3.14
print('{0:.3f}'.format(3.1415926))
输出结果:
3.142
print('{0:10.3f}'.format(3.1415926)) # 宽度为10位,保留三位小数
输出结果:
3.142
16.6 字符串的编码转化
为什么需要字符串的编解码
编码与解码的方式
编码:将字符串转化为二进制数据(bytes)
解码:将bytes类型的数据转化成字符串类型
# 编码格式
s='天涯共此时'
print(s.encode(encoding='gbk')) # 在gbk这种编码格式中一个中文占2个字节
print(s.encode(encoding='utf-8')) # 在utf-8这种编码格式中一个中文占3个字节
输出结果:
b'/xcc/xec/xd1/xc4/xb9/xb2/xb4/xcb/xca/xb1'
b'/xe5/xa4/xa9/xe6/xb6/xaf/xe5/x85/xb1/xe6/xad/xa4/xe6/x97/xb6'
# 解码格式
byte=s.encode(encoding='gbk')
print(byte.decode(encoding='gbk')) # byte代表的是二进制数据
输出结果:
天涯共此时
byte=s.encode(encoding='utf-8')
print(byte.decode(encoding='utf-8')) # byte代表的是二进制数据
输出结果:
天涯共此时
17 函数
17.1函数的创建与调用
函数的定义:函数就是执行特定任务和以完成特定功能的一段代码(榨汁机);
为什么使用函数:复用代码,隐藏实现细节,提高可维护性,提高可读性便于调试;
函数的创建:
1 def 函数名 ([输入参数]): # 函数名符合标识符的规范自命名
2 函数体 # 实现功能
3 [return xxx] # 接收结果的容器(变量)
4 def calc(a,b):
5 c=a+b
6 return c # 结束函数体并将结果提交,提交给函数的调用处
7 res = calc(99,999) # 调用
8 print(res)
输出结果:
1098
解释:
当执行在第7行的时候,将值赋值给a与b输出的结果给调用处打印输出
17.2函数的参数传递
形式参数(形参)
def calc(a,b): # a,b称为形式参数,形式参数在函数的定义处
实际参数(实参)
res = calc(99,999) # 10,20称为实参,实参在函数的调用处
函数调用的参数传递方式:
位置实参:根据形参对应的位置进行实参传递
res = calc(99,999)
关键字实参:根据形参名称进行实参传递
res = calc(b=999,a=99) # 等号左侧的字母称为关键字参数
函数参数传递调用的内存分析:
传参的可变对象与不可变对象
# 定义函数
def fun(arg1,arg2):
print('arg1',arg1)
print('arg2',arg2)
arg1=100
arg2.append(10)
print('arg1', arg1)
print('arg2', arg2)
# 调用函数
n1=11
n2=[90,50,78]
print('n1',n1)
print('n2',n2)
fun(n1,n2) # 位置传参,实参名称可以与形参名称不一致
print('n1',n1) # n1=11,
print('n2',n2)
'''在函数调用的过程中,进行参数的传递
如果是不可变对象n1,在函数体的修改不会影响实参的值,arg1的值改为100,不会影响;
如果是可变对象n2,在函数体的修改下会影响实参的值,arg2的列表中append(10),会影响n2的值'''
输出结果:
n1 11
n2 [90, 50, 78]
arg1 11
arg2 [90, 50, 78]
arg1 100
arg2 [90, 50, 78, 10]
n1 11
n2 [90, 50, 78, 10]
17.3函数的返回值
函数的返回值:
1.如果函数没有返回值(函数执行完毕之后,不需要给调用处提供数据),return可以省略不写;
def fun1():
print('hello')
return # 可以省略不写
fun1()
输出结果:
hello
2.函数的返回值如果是1个,直接返回原类型
def fun1():
return 'hello'
stt=fun1()
print(stt)
输出结果:
hello
3.函数的返回值,如果是多个,返回的结果为元组
def fun2():
return 'hello','python'
print(fun2())
输出结果:
('hello', 'python')
# 不能严格按照函数结构写
# 定义函数
def fun(num):
odd=[] # 存奇数
even=[] # 存偶数
for i in num:
if i%2: # 奇数为1,布尔值为True
odd.append(i)
else:
even.append(i)
return odd,even
lst=[10,55,88,98,78,56,69,33]
print(fun(lst))
输出结果:
([55, 69, 33], [10, 88, 98, 78, 56])
17.4函数的参数定义
默认值参数:
'''
函数定义默认值参数:函数定义时,给形参设置默认值,只有与默认值不符的时候才需要传递实参
'''
def funn(a,b=10):
print(a,b)
funn(100) # 只传一个参数,b采用默认值
funn(10,20) # 20将默认值替换
输出结果:
100 10
10 20
个数可变的位置参数:
定义函数时,可能无法事先确定传递的位置实参的个数时,使用可变的位置参数;使用*定义个数可变的位置形参;结果为一个元组
def fun(*args): # 只能是一个参数,args是一个自定义参数
print(args)
fun(10)
fun(10,20)
fun(10,30,50)
输出结果:
(10,)
(10, 20)
(10, 30, 50)
个数可变的关键字形参:
定义函数时,无法事先确定传递的关键字实参的个数时,使用可变的关键字形参;使用**定义个数可变的关键字形参;结果为一个字典
def fun(**args): # 只能是一个参数
print(args)
fun(a=10)
fun(a=10,b=20)
fun(a=10,b=30,c=50)
输出结果:
{'a': 10}
{'a': 10, 'b': 20}
{'a': 10, 'b': 30, 'c': 50}
在一个函数定义过程中,既有个数可变关键字形参,也有个数可变位置形参,个数可变的位置形参就在个数可变的关键字形参之前!这样就不会报错;
函数的参数总结:
函数调用时的参数传递:
'''函数调用时的参数--位置/关键字实参'''
# 将列表中的元素都转换为位置实参--使用*
def fun(a,b,c): # a,b,c在函数的定义处,所以是形式参数
print('a=',a)
print('b=',b)
print('c=',c)
fun(10,20,30) # 函数调用时的参数传递,称为位置传参
lst=[50,70,10]
fun(*lst) # 在函数调用时将列表中的每一个元素都转换为位置实参传入
输出结果:
a= 10
b= 20
c= 30
a= 50
b= 70
c= 10
# 将字典中的每个键值对都关键字实参--使用**
fun(a=100,b=200,c=300) # 函数的调用处,关键字传参
dic={'a':111,'b':222,'c':333}
fun(**dic) # 在函数调用时,将字典的每一个键值对转化为关键字实参传入
输出结果:
a= 100
b= 200
c= 300
a= 111
b= 222
c= 333
函数定义时的参数传递:
def fun3(a,b,c,d): # *从这个*之后的参数在函数调用只能采用关键字传递 def fun3(a,b,*,c,d)
print('a',a)
print('b',b)
print('c',c)
print('d',d)
fun3(88,99,111,255) # 位置传参
fun3(a=45,b=55,c=65,d=85) # 关键字传参
fun3(10,20,c=40,d=50) # 前两个是位置实参传递,后两个是关键字实参传递
# 函数定义时参数的形参的顺序问题
def fun4(a,b,*,c,d,**args):
pass
def fun6(*args,**args2):
pass
def fun7(a,b=10,*args,**args2):
pass
输出函数:
a 88
b 99
c 111
d 255
a 45
b 55
c 65
d 85
a 10
b 20
c 40
d 50
17.5变量的作用域
程序代码能访问该变量的区域;
根据变量的有效范围可分为:
局部变量:在函数内定义的并使用的变量,只在函数内部有效,局部变量使用global声明,这个变量就会变为全局变量;
全局变量函数体外定义的变量,可作用于函数体外;
def fun(a,b):
c=a+b # c称为局部变量,因为c是函数体内定义的变量,a和b为函数的形参,作用范围也是函数内部,相当于局部变量
print(c)
# print(a) 报错,a与c超出了局部变量的范围(超出了作用域)
# print(c)
name='样老师' # name的作用范围为内部和外部都可以使用,称为全局变量
print(name)
def fun2():
print('杨老师')
fun2()
def fun3():
global age # 函数内部定义的变量为局部变量,局部变量使用global声明,这个变量就是全局变量
age=20
print(age)
fun3()
print(age)
输出结果:
样老师
杨老师
20
20
17.6递归函数
定义:如果在一个函数的函数体内调用了该函数本身,这个函数就称为递归函数;
组成部分:递归调用与递归终止条件;
调用过程:每递归调用一次函数,都会在站内存分配一个栈针;每执行完一次函数,都会释放相应的空间
优缺点:缺点:占用内存多,效率低下;优点:思路和代码简单
def fun(n): # 计算阶乘的数
if n==1:
return 1
else:
return n*fun(n-1)
print(fun(6))
输出结果:720
解释:从上到下递推,从下到上回归(还需理解)
fun(6) 720
|
6*fun(5) 6*(120)
|
6*(5*fun(4)) 6*(5*24)
|
6*(5*(4*fun(3))) 6*(5*(4*6))
|
6*(5*(4*(3*fun(2)))) 6*(5*(4*(3*2)))
|
6*(5*(4*(3*(2*fun(1))))) 6*(5*(4*(3*(2*1))))
18 斐波那契数列
def fib(n): # n代表第几位数
if n==1:
return 1
elif n==2:
return 1
else:
return fib(n-1)+fib(n-2)
print(fib(7))
# 1 1 2 3 5 8 13 ...
# 输出前六位数字
for i in range(1,7):
print(fib(i))
输出结果:
13
1
1
2
3
5
8
补充递归是什么:程序调用自身的编程技巧。
19 对象
19.1两大编程思想
面向过程与面向对象:
面向过程 | 面向对象 | |
---|---|---|
区别 | 事物比较简单,可以用线性的思维去解决(实际操作思想) | 事物比较复杂(宏观),使用简单的线性思维无法解决 |
共同点 | 都是解决实际问题的一种思维方式 | |
二者相辅相成,并不是对立的;解决复杂问题,通过面向对象的方式便于我们从宏观上把握事物之间的复杂关系,方便我们分析整个系统;具体到微观操作,仍然使用面向过程方式来处理 |
19.2类和对象的创建
类是多个类似事物组成的群体的统称,能够判断
1.数据类型:不同的数据类型属于不同的类;使用内置函数查看数据类型type()
2.对象:100、99、520都是int类之下包含的相似的不同个例,这个个例专业术语称为实例或对象
3.类的创建:
class Student: # Student 类名;由一个或多个单词组成,每个单词的首字母大写,其余小写
pass
# python 中一切皆对象,Student是对象吗?有内存空间吗?
print(id(Student))
print(type(Student))
print(Student)
输出结果:
2800713235104
<class 'type'>
<class '__main__.Student'>
4.类的组成:
class Student: # Student 类名;由一个或多个单词组成,每个单词的首字母大写,其余小写
native_place='吉林' # 直接写在类里的变量,称为类属性
def __init__(self,name,age): # 初始化变量
self.name=name # self.name称为实例属性,进行了一个赋值操作,将局部变量的name的值赋值给实体属性
self.age=age
# 定义在类内部称为实例方法:传的是实例对象
def study(self):
print('我在实习...')
# 静态方法
@staticmethod
def method():
print('我使用了staticmethod进行修饰,所以我是静态方法')
# 类方法
@classmethod
def cm(cls):
print('我是类方法,因为我使用了classmethod进行修饰')
19.3类对象与类属性
1.对象的创建:又称为类的实例化
语法: 实例名=类名( )
例子:
class Student: # Student 类名;由一个或多个单词组成,每个单词的首字母大写,其余小写
native_place='吉林' # 直接写在类里的变量,称为类属性
def __init__(self,name,age): # 初始化变量
self.name=name # self.name称为实例属性,进行了一个赋值操作,将局部变量的name的值赋值给实体属性
self.age=age
# 定义在类内部称为实例方法:传的是实例对象
def study(self):
print('我在实习...')
# 创建Student类的实例对象
stu=Student('张三',20) # 实例对象(有类指针),会指向类对象
print(id(stu)) # Student类的实例对象的内存地址
print(type(stu))
print(stu)
输出结果:
1761611947792
<class '__main__.Student'>
<__main__.Student object at 0x0000019A28411F10>
class Student: # Student 类名;由一个或多个单词组成,每个单词的首字母大写,其余小写
native_place='吉林' # 直接写在类里的变量,称为类属性
def __init__(self,name,age): # 初始化变量
self.name=name # self.name称为实例属性,进行了一个赋值操作,将局部变量的name的值赋值给实体属性
self.age=age
# 定义在类内部称为实例方法
def study(self):
print('我在实习...')
# 创建Student类的实例对象
stu=Student('张三',20) # 实例对象(有类指针),会指向类对象调用类对象
stu.study() # 对象名.方法名 实例方法
print(stu.name) # 实例属性
print(stu.age)
# 类名.方法名(类的对象)--实际上就是方法定义处的self
Student.study(stu) # 与stu.study()功能相同,都是调用student的study方法
输出结果:
我在实习...
张三
20
我在实习...
19.4类方法与静态方法
遗留:两者区别!
class Student: # Student 类名;由一个或多个单词组成,每个单词的首字母大写,其余小写
native_place='吉林' # 直接写在类里的变量,称为类属性(类中方法外的变量称为类属性,被该类的所有对象所共享)
def __init__(self,name,age): # 初始化变量
self.name=name # self.name称为实例属性,进行了一个赋值操作,将局部变量的name的值赋值给实体属性
self.age=age
# 定义在类内部称为实例方法
def study(self):
print('我在实习...')
stu = Student('张三',40)
stu1 = Student('李四',35)
print(stu.native_place)
print(stu1.native_place)
Student.native_place = '北京'
print(stu.native_place)
print(stu1.native_place)
输出结果:
吉林
吉林
北京
北京
类方法:
使用@classmethod修饰的方法,使用类名直接访问
class Student: # Student 类名;由一个或多个单词组成,每个单词的首字母大写,其余小写
native_place='吉林' # 直接写在类里的变量,称为类属性
def __init__(self,name,age): # 初始化变量
self.name=name # self.name称为实例属性,进行了一个赋值操作,将局部变量的name的值赋值给实体属性
self.age=age
# 定义在类内部称为实例方法
def study(self):
print('我在实习...')
@classmethod
def cm(cls):
print('我是类方法,因为我使用了classmethod修饰')
Student.cm()
输出结果:
我是类方法,因为我使用了classmethod修饰
静态方法:
使用@staticmethod修饰的方法,使用类名直接访问
class Student: # Student 类名;由一个或多个单词组成,每个单词的首字母大写,其余小写
native_place='吉林' # 直接写在类里的变量,称为类属性
def __init__(self,name,age): # 初始化变量
self.name=name # self.name称为实例属性,进行了一个赋值操作,将局部变量的name的值赋值给实体属性
self.age=age
# 定义在类内部称为实例方法
def study(self):
print('我在实习...')
@staticmethod
def stamen():
print('我是静态方法,因为我使用了staticmenthod')
Student.stamen()
输出结果:
我是静态方法,因为我使用了staticmenthod
19.5动态绑定属性和方法
Python是动态语言,在创建对象之后可以动态的绑定属性和方法
class Student():
def __init__(self,name,age):
self.name = name # 实例化变量=局部变量
self.age = age
def eat(self):
print('在吃饭')
stu1 = Student('张三',20)
stu2 = Student('马武',47)
# 动态绑定属性
stu2.gender = '女'
print(stu1.name,stu1.age)
print(stu2.name,stu2.age,stu2.gender)
# 动态绑定方法
def show(): # 函数
print('动态绑定方法')
stu1.show = show # 方法
stu1.show()
输出结果:
张三 20
马武 47 女
动态绑定方法
python类函数有self和没self的区别:有self必须创建实例;没有self可以直接用类名调用函数。
19.6面向对象的三大特征
封装:提高程序的安全性;
将数据(属性)和行为(方法)包装在类对象中。在方法内部对属性进行操作,在类对象的外部调用方法。这样,无需关心方法内部的具体实现细节,从而隔离了复杂度。
在python中没有专门的修饰符用于属性的私有,如果该属性不希望在类对象外部被访问,前边使用两个“_”
class Car():
def __init__(self,brand): # brand 是类的一个属性
self.brand = brand
def start(self):
print('汽车已启动')
car = Car('大众')
Car.start(car) # car.start()
print(car.brand)
输出结果:
汽车已启动
大众
class Student():
def __init__(self,name,age):
self.name = name
self.__age = age # 不希望在类的外部调用
def show(self):
print(self.name,self.__age)
stu = Student('lisi',20)
stu.show()
print(stu.name)
# print(stu.__age) 出错不能调用
print(dir(stu))
print(stu._Student__age)
输出结果:
lisi 20
lisi
['_Student__age', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name', 'show']
20
继承:提高代码的复用性
语法格式:
class 子类类名(父类1,父类2,...):
pass
#如果一个类没有继承任何类,则默认继承object
#python支持多继承
#定义子类时,必须在其构造函数中调用父类的构造函数
class Person(object):
def __init__(self,name,age):
self.name=name
self.age=age
def info(self):
print(self.name,self.age)
class Student(Person):
def __init__(self,name,age,stunum):
super().__init__(name,age) # super函数是用来调用父类(超类)的一个方法;
self.stunum=stunum
class Teacher(Person):
def __init__(self,name,age,teachyear):
super().__init__(name,age)
self.teachyear=teachyear
student=Student('李四',23,'18010832')
teacher=Teacher('么妹',60,23)
student.info()
teacher.info()
输出结果:
李四 23
幺妹 23
class A(object):
pass
class B(object):
pass
class C(A,B):
pass
方法重写:
如果子类对继承的父类的某个属性或方法不满意,可以在子类中对其(方法体)进行重新编写;
子类重写后的方法:super().xxx()调用父类中被重写的方法;
class Person(object):
def __init__(self,name,age):
self.name=name
self.age=age
def info(self):
print(self.name,self.age)
class Student(Person):
def __init__(self,name,age,stunum):
super().__init__(name,age)
self.stunum=stunum
def info(self):
super().info()
print(self.stunum)
class Teacher(Person):
def __init__(self,name,age,teachyear):
super().__init__(name,age)
self.teachyear=teachyear
def info(self):
super().info()
print(self.teachyear)
student=Student('李四',23,'18010832')
teacher=Teacher('么妹',60,23)
student.info()
teacher.info()
输出结果:
李四 23
18010832
么妹 60
23
object类:
是所有类的父类,因此所有类都有object类的属性和方法;
内置函数dir()可以查看指定对象所有的属性;
object有一个____str____()方法,用于返回一个对于“对象的描述”,对应于内置函数str()经常用于print()方法,帮我们查看对象的信息,所以我们经常会对____str____()进行重写.
class Student():
pass
stu=Student()
print(dir(stu))
print(stu)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
<__main__.Student object at 0x00000186A9217400> 返回对象的描述
重写____str____()方法
class Person:
def __init__(self,name,age):
self.name=name
self.age=age
def __str__(self):
return '我的名字叫{0},今年{1}岁'.format(self.name,self.age)
stu=Person("马丽荣",23)
print(dir(stu)) #可以查看指定对象所有属性
print(type(stu))
print(stu)
输出结果:
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'name']
<class '__main__.Person'>
我的名字叫马丽荣,今年23岁
多态:提高程序的可扩展性和可维护性
即便不知道一个变量所引用的对象到底是什么类型,仍然可以通过这个变量调用方法,在运行过程中根据变量所引用对象类型,动态调用哪个对象中的方法
class Anmial(object):
def eat(self):
print("动物要吃...")
class Dog(Anmial):
def eat(self):
print("狗吃骨头...")
class Cat(Anmial):
def eat(self):
print("猫猫爱吃鱼...")
class Person(object):
def eat(self):
print("人吃五谷杂粮...")
def func(anmi):
anmi.eat() # 不关心对象的类型,只关系该对象是否具有eat的行为
func(Dog())
func(Cat())
func(Person())
func(Anmial())
输出结果:
狗吃骨头...
猫猫爱吃鱼...
人吃五谷杂粮...
动物要吃...
person不存在继承关系,但是有eat方法;
python是动态语言,可以动态的绑定属性和方法,不需要关心person是谁的子类,关心person是否有eat属性或方法;
19.7特殊属性和特殊方法
特殊属性:dict() 获得类对象或实例对象所绑定的所有属性和方法的字典
class A:
pass
class B:
pass
class C(A,B):
def __init__(self,name,age):
self.name=name
self.age=age
class D(A):
pass
#创建C类对象
x=C('Jack',20) # x是C类型的实例对象;
print(x.__dict__) #实例对象的属性字典
print(C.__dict__)
print(x.__class__) # 输出对象所属的类
print(C.__bases__) # C类的父类类型的元素
print(C.__base__) # 类的基类
print(C.__mro__) # 类的层次结构
print(A.__subclasses__())
输出结果:
{'name': 'Jack', 'age': 20}
{'__module__': '__main__', '__init__': <function C.__init__ at 0x000002450577D670>, '__doc__': None}
<class '__main__.C'>
(<class '__main__.A'>, <class '__main__.B'>)
<class '__main__.A'>
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
[<class '__main__.C'>, <class '__main__.D'>]
__init__ __new__ 方法:
class Students(object):
def __new__(cls, *args, **kwargs): # 用于创建对象
print('__new__被调用执行了,cls的id值为:{0}'.format(id(cls))) # 4608
objj=super().__new__(cls)
print('创建的对象的id为:{0}'.format(id(objj))) # 3824
return objj
def __init__(self,name,age): # 对创建的对象进行初始化
print('__init__方法调用了id:{0}'.format(id(self))) # 3824
self.name = name
self.age = age
print("输出Student类的的id:{0}".format(id(Students))) # 4608
print("输出object对象的id:{0}".format(id(object))) # 2336
stu = Students("张三",20)
print("输出实例对象stuid:{0}".format(id(stu))) # 3824
cls是类方法里面的第一个参数,表示类本身;self是实例方法里的第一个参数,表示对象本身。
19.8 类的浅拷贝与深拷贝
变量的赋值操作:只是形成了两个变量,实际上还是指向同一个对象
class CPU:
pass
class Disk:
pass
class Computer:
def __init__(self,cpu,disk):
self.cpu = cpu
self.disk =disk
# 变量的赋值
cpu1 = CPU()
cpu2 = cpu1
print(cpu1,id(cpu1))
print(cpu2,id(cpu2))
输出结果:
<__main__.CPU object at 0x000001F0FA767400> 2134505845760
<__main__.CPU object at 0x000001F0FA767400> 2134505845760
浅拷贝:python拷贝一般都是浅拷贝,拷贝时对象包含的子对象不拷贝,因此,原对象与拷贝对象会引用同一个子对象。(是重新建立了一个Computer实例对象,相当于原来的实例对象id变了,但是value不变,因此新拷贝出来的computer实例对象cpu和disk还是原来的)
class CPU:
pass
class Disk:
pass
class Computer:
def __init__(self,cpu,disk):
self.cpu = cpu
self.disk =disk
cpu1 = CPU()
# 类的浅拷贝
disk = Disk()
computer = Computer(cpu1,disk)
import copy
computer2 = copy.copy(computer)
print(computer,computer.cpu,computer.disk)
print(computer2,computer2.cpu,computer2.disk)
输出结果:
<__main__.Computer object at 0x0000019CA5AB4640> <__main__.CPU object at 0x0000019CA5AC7400> <__main__.Disk object at 0x0000019CA5B41CA0>
<__main__.Computer object at 0x0000019CA5BBA070> <__main__.CPU object at 0x0000019CA5AC7400> <__main__.Disk object at 0x0000019CA5B41CA0>
深拷贝:使用copy模块的deepcopy函数,递归拷贝对象中包含的子对象,源对象和拷贝对象所有的的子对象也不相同。
class CPU:
pass
class Disk:
pass
class Computer:
def __init__(self,cpu,disk):
self.cpu = cpu
self.disk =disk
cpu1 = CPU()
disk = Disk()
computer = Computer(cpu1,disk)
import copy
computer3 = copy.deepcopy(computer)
print(computer,computer.cpu,computer.disk)
print(computer3,computer3.cpu,computer3.disk)
输出结果:
<__main__.Computer object at 0x0000021BD3C64640> <__main__.CPU object at 0x0000021BD3C77400> <__main__.Disk object at 0x0000021BD58A1CA0>
<__main__.Computer object at 0x0000021BD591A130> <__main__.CPU object at 0x0000021BD5966D30> <__main__.Disk object at 0x0000021BD5983AC0>
20 模块
20.1 什么是模块__模块化编程的好处
模块:Modules
函数与模块的关系:一个模块中可以包含N多个函数;
在python中一个扩展名为.py的文件就是一个模块;
使用模块的好处:方便其它程序和脚本的导入并使用;避免函数名和变量名冲突;提高代码的可维护性与可重用性。
20.2 模块的导入
创建模块:新建一个.py文件,名称尽量不要与python自带的标准模块名称相同
导入模块:
import 模块名称 [as 别名]
from 模块名称 import 函数/变量/类
import math
print(math.pi)
print(math.pow(2,3))
print(math.ceil(9.001))
print(math.floor(9.999))
输出结果:
3.141592653589793
8.0
10
9
或者这样写...
from math import pi
from math import pow
print(pi)
print(pow(2,3))
输出结果:
3.141592653589793
8.0
导入自定义模块:
新建名为calc.py的模块,写入内容为
def add(a,b):
return a+b
def div(c,d):
return (c/d)
再新建文件.py,引入自定义的模块
import calc
print(calc.add(2, 3))
print(calc.div(10,4))
输出结果:
5
2.5
也可以这样写:
from calc import add
from calc import div
print(add(2,3))
print(div(10,4))
输出结果:
5
2.5
20.3 以主程序的方式运行
在每个的模块的定义中都包括一个记录模块名称的变量____name____,程序可以检查该变量,以确定他们在哪个模块中执行。如果一个模块不是被导入到其它程序中执行,那么他可能在解释器的顶级模块中执行。顶级模块的____name____变量值为____main____
if __name__ == '__main__':
pass
# 输入“main”,回车就会输出 if __name__ == '__main__':
新建文件calc2:
def add(a,b):
return a+b
if __name__ == '__main__': # 只有当运行calc2的时候才会输出“print”
print(add(10,24))
再新建另一个文件demo0:
import calc2
print(calc2.add(10,20)) # 不会再输出导入的模块calc2的print...
20.4 python中的包
包是一个分层次的目录结构,它将一组功能相近的模块组织在一个目录下;
作用:代码规范、避免模块名冲突;
包与目录的区别:包包含init.py文件的目录称为包;目录里通常不包含init.py文件;
Python程序下有多个包,每个包下有与之对应的多个模块,每个模块中就有类,函数属性等…
包的导入:
import 包名.模块名
右键模块:“new package”, “new directory”
右键package1“new python file” –module1.py(写入a=1)与module2.py(写入b=2)
jichu下新建py文件-demo3,在demo3导入包:
import package1.module1
print(package1.module1.a)
或者可以这样写
import package1.module1 as KK # KK是package1.module1的别名
print(KK.a)
输出结果:
1
导入包的模块时注意事项:
使用import导入时只能跟包名或模块名
import module
import package
使用from ... import导入时可以跟包,模块,函数,变量
from package import module1
from package.module import a
20.5 python中常见的内置模块
模块名 | 描述 |
---|---|
sys | 与python解释器及其环境操作相关的标准库 |
time | 提供与时间相关的各种函数的标准库 |
os | 提供了访问操作系统服务功能的标准库 |
calender | 提供了与日期相关的各种函数的标准库 |
urllib | 用于读取来自网上的(服务器)的数据标准库 |
json | 用于使用JSON序列化和返序列化对象 |
re | 用于在字符串中执行正则表达式匹配和替换 |
math | 提供标准算数运算函数的标准库 |
decimal | 用于进行精确控制运算精度、有效数位和四舍五入操作的的十进制运算 |
logging | 提供了灵活的记录事件、错误、警告和调试信息等日志的信息功能。 |
补充一个me不知道的知识点:json文件是存储数据结构和对象的文件,在web应用程序中进行数据交换。
# 获取对象的内存大小
import sys
print(sys.getsizeof(24))
print(sys.getsizeof(str))
# 获取时间
import time
print(time.time()) # 输出为秒
print(time.localtime(time.time())) # 转为本地时间
输出结果:
1650168268.3991244
time.struct_time(tm_year=2022, tm_mon=4, tm_mday=17, tm_hour=12, tm_min=4, tm_sec=28, tm_wday=6, tm_yday=107, tm_isdst=0)
# 读取百度
import urllib.request
print(urllib.request.urlopen('http://www.baidu.com').read())
20.6 第三方模块的安装与使用
第三方模块的在线安装:
pip install schedule
C:/Users>python
>>> import schedule # 无回显表示安装成功
第三方模块的使用:
import 模块名
import schedule
import time
def job():
print('哈哈,嘻嘻...')
schedule.every(3).seconds.do(job)
while True: # 无线循环语句
schedule.run_pending()
time.sleep(1)
补充作业:自动化发送信息(qq,wx,mail)怎末写!!??
20.7 编码格式的介绍
常见的字符编码格式:
python的解释器使用的是Unicode(内存);
.py文件在磁盘上使用的是UTF-8(外存)
不同的编码格式决定占用的磁盘空间大小。
更改编码格式:
#encoding=gbk
20.8 文件读写的原理__读取磁盘文件中的内容
文件的读写操作俗称“IO操作”;
文件读写操作流程:
操作原理:
.py文件是由解释器去执行,解释器调用操作系统资源操作磁盘上的文件,对硬盘上的文件进行读和写的操作。打开一个python文件后,应用程序的数据运行在内存中,从内存中拿取数据到应用程序叫读,向内存中输出数据叫做写。
内置函数open()创建文件对象:
语法规则:
file = open(filename [,mode,encoding])
被创建的文件对象 要创建或打开的文件名称 打开模式默认为只读 默认文本文件txt中字符的编码格式为gbk;
新建文本文档wendang.txt(默认编码格式是gbk):
中国
美丽
新建.py文件:
file=open('wenben.txt','r',encoding='utf-8') # 将txt的编码格式转换为.py文件默认的编码格式utf-8
print(file.readlines())
file.close()
输出结果: # 列表形式输出
['中国/n', '美丽']
20.9 常用的文件打开模式
文件的类型:按文件中数据的组织形式,文件分为以下两大类
文本文件:存储的是普通的“字符文本”,默认为Unicode字符集,可以使用记事本程序打开;
二进制文件:把数据内容用“字节”存储,无法用记事本打开,必须使用专用的软件打开,举例:MP3音频文件 .jpg图片 .doc文档等。
# r
file=open('123.txt','w') # 有该文件写入内容覆盖,没有该文件则创建文件写入内容
file.write('python')
file.close()
输出结果:
有该文件且文件内容为什么都会被写入的内容覆盖掉;
没有该文件则会有新的文件123.txt创建,写入内容
python
#a
file=open('123.txt','a') # 追加内容
file.write('python')
file.close()
在已有的123.tex文件中输出结果:
pythonpython
src_file=open('photo.jpg','rb')
targt_file=open('copyphoto.jpg','wb')
targt_file.write(src_file.read())
src_file.close()
targt_file.close()
打开模式 | 描述 |
---|---|
r | 以只读模式打开文件,文件的指针将会放在文件的开头 |
w | 以只写模式打开文件,如果文件不存在则创建,如果文件存在,则覆盖原有内容,文件指针在文件的开头 |
a | 以追加模式打开文件,如果文件不存在则创建,如果文件存在,则在文件末尾追加内容,文件指针在源文件末尾 |
b | 以二进制文件打开文件,不能单独使用,需要与共它模式一起使用,rb,或者wb |
+ | 以读写方式打开文件,不能单独使用,需要与其它模式一起使用,a+ |
20.10 文件对象的常用方法
方法名 | 说明 |
---|---|
read([size]) | 从文件中读取size个字节或字符的内容返回。若省略[size]则读取到文件末尾,即一次读取文件所有内容;注意一点的是:read会在控制器上输出。 |
readline() | 从文本文件中读取一行内容 |
readlines() | 把文本文件中每一行都作为独立的字符串对象,并将这些对象放入列表返回 |
write(str) | 将字符串内容写入文件 |
writelines(s_list) | 将字符串s_list写入文本文件,不添加换行符 |
seek(offset[,whence]) | 把文件指针移动到新的位置,offset表示相对于whence的位置:offset:为正往结束方向移动,为负往开始方向移动。whence不同的值代表不同的而含义:0,从文件开头计算(默认值);1,从当前位置开始算;2,从文件尾开始算 |
tell() | 返回文件指定的当前位置 |
flush() | 把缓冲区的内容写入文件,但不关闭文件 |
close() | 把缓冲区的内容写入文件,同时关闭文件,释放文件对象相关的资源。 |
a.txt内容为
中国
美丽
读:
file = open('a.txt', 'r', encoding='UTF-8')
print(file.read())
输出结果:
中国
美丽
file = open('a.txt', 'r', encoding='UTF-8')
print(file.read(2))
输出结果:
中国
file = open('a.txt', 'r', encoding='UTF-8')
print(file.readline())
输出结果:
中国
file = open('a.txt', 'r', encoding='UTF-8')
print(file.readlines())
输出结果:
['中国/n', '美丽']
写:
file = open('c.txt', 'a')
file.write('hello') # 将字符串写入内容
file.close() # 创建名为c.txt文件内容为“hello”
file = open('c.txt', 'a')
lst = ['java','go','python']
file.writelines(lst)
file.close() # c.txt文件中内容为 “hellojavagopython”
file = open('d.txt', 'r',encoding='utf-8')
file.seek(3) # 一个中文占2个字节,光标停在“中之前”
print(file.read())
file.close()
输出结果:
国
美丽
file = open('d.txt', 'r',encoding='utf-8')
print(file.read())
print(file.tell()) # 14字节
file.close()
输出结果:
中国
美丽
14
file = open('f.txt', 'a')
file.write('enheng')
file.flush() # 数据是会先写在缓存里的
file.write('aha')
file.close()
输出结果:
enhengaha
20.11 with语句(上下文管理器)
with语句可以自动管理上下文资源,不论什么原因跳出with块,都能确保文件正确的关闭,以此来达到释放资源的目的。
with open('f.txt','r',encoding='utf-8') as file:
print(file.read())
open('f.txt','r',encoding='utf-8')称为上下文表达式,对象称为上下文管理器
上下文管理器:一个类对象实现了特殊方法____enter____与____exit____,那么称类对象遵守上下文关系协议,而这个类的实例对象就称为上下文管理器。
语言解释:
class MyContentMgr(object):
def __enter__(self):
print("__enter__方法被调用了")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("__exit__被调用执行了")
def show(self):
print('show方法被调用执行了')
with MyContentMgr() as file: # 相当于MycontentMgr=file
file.show()
输出结果:
__enter__方法被调用了
show方法被调用执行了
__exit__被调用执行了
不管有无异常还是会调用exit方法退出 叫做自动关闭资源
建议用with语句写打开文件
with open('789.jpg', 'rb') as src_file:
with open('9810.jpg','wb') as targ_file:
targ_file.write(src_file.read())
20.12 os模块的常用函数
目录操作:os模块是python内置的与操作系统功能和文件系统相关的模块,该模块中的语句的执行结果通常与操作系统有关,在不同的操作系统上运行,得到的结果可能不一样。os模块与os.path模块用于对目录或文件进行操作。
import os
os.system('notepad.exe') # 打开记事本应用程序
os.system('calc.exe') # 打开计算机应运程序
# 直接调用可执行文件
os.startfile('C://Program Files (x86)//Tencent//QQ//Bin//qq.exe') # 登录应用程序qq
os模块操作目录相关函数:
函数 | 说明 |
---|---|
getcwd() | 返回当前的工作(文件.py)目录 |
listdir(path) | 返回指定路径下的文件 和目录信息 |
mkdir(path[,mode]) | 创建目录 |
makedirs(path1/path2…[,mode]) | 创建多级目录 |
rmdir(path) | 删除目录 |
removedirs(path1/path2) | 删除多级目录 |
chdir(path) | 将path设置为当前工作目录 |
import os
print(os.getcwd())
lis = os.listdir('../jichu') # 注意是“/”
print(lis)
os.mkdir('newpy') # 默认目录路径与当前写的程序的文件在一个路径下
os.makedirs('A/B/C')
os.rmdir('newpy.py')
os.removedirs('A/B/C')
import os
print(os.getcwd())
os.chdir('E://(network)//python资料及练习//python学习-练习//project')
print(os.getcwd())
输出结果:
E:/(network)/python资料及练习/python学习-练习/jichu
E:/(network)/python资料及练习/python学习-练习/project
20.13 os.path模块的常用方法
函数 | 说明 |
---|---|
abspath(path) | 用于获取文件或目录的绝对路径 |
exists(path) | 用于判断文件或目录是否存在,如果存在返回True,否则返回False |
join(path,name) | 将目录与目录或者文件名拼接起来 |
splitext() | 分离文件名和扩展名 |
basename(path) | 从一个目录中提取文件名 |
split() | 目录与文件拆分 |
dirname(path) | 从一个路径中提取文件路径,不包括文件名 |
isdir(path) | 用于判断是否为路径 |
import os.path
print(os.path.abspath('project')) # 目录的绝对路径
print(os.path.exists('jichu'),os.path.exists('calc.py'))
print(os.path.join('E://Python','demo110.py'))
print(os.path.split('E:/(network)/python资料及练习/python学习-练习/jichu')) #目录与文件拆分
print(os.path.splitext('bug.py'))
print(os.path.basename('E:/(network)/python资料及练习/python学习-练习/jichu/leiyuduixiang.py'))
print(os.path.dirname('E:/(network)/python资料及练习/python学习-练习/jichu/leiyuduixiang.pyd'))
print(os.path.isdir('E:/(network)/python资料及练习/python学习-练习/jichu'))
输出结果:
E:/(network)/python资料及练习/python学习-练习/project
True False
E:/Python/demo110.py
('E://(network)//python资料及练习//python学习-练习', 'jichu')
('bug', '.py')
leiyuduixiang.py
E:/(network)/python资料及练习/python学习-练习/jichu
True
练习:获取当前目录下的所有.pyw文件
import os
path = os.getcwd()
pyfile = os.listdir(path)
for file in pyfile:
if file.endswith('.py'): # 以什么结尾
print(file)
walk()方法:递归遍历指定目录下所有的文件和目录。而且将目录下的子目录都遍历出来。
import os
path = os.getcwd()
lis_files = os.walk(path) # 返回为一个元组
print(lis_files) # 是一个迭代器对象 <generator object walk at 0x00000148F96ED7B0>
for dirpath,dirname,filename in lis_files:
print(dirpath)
print(filename)
print(dirname)
print('------------------') # 不仅遍历出当前目录、文件,还遍历出子目录与子文件
输出结果:
<generator object walk at 0x00000134139F3740>
E:/(network)/python资料及练习/python学习-练习/jichu
['123.txt', '789.jpg', '9810.jpg', 'a.txt', 'bug.py', 'c.txt', 'calc.py', 'copyphoto.jpg', 'd.txt', 'demo19.py', 'demo3.py', 'f.txt', 'leiyuduixiang.py', 'Object类.py', 'os模块.py', 'os模块函数.py', 'with语句复制图片.py', '上下文管理器.py', '主程序1.py', '主程序2.py', '内置模块.py', '在线安装三方模块使用.py', '多态.py', '引入自定义模块.py', '斐波那契数列.py', '模块.py', '深拷贝与浅拷贝.py', '特殊方法.py', '特殊方法2.py', '生活照10.jpg', '类方法与静态方法.py', '继承.py', '获取.py文件.py', '试试.py', '读写方法.py', '读取文件.py', '调试.py']
['directory1', 'me', 'newpy', 'package1', '__pycache__']
------------------
E:/(network)/python资料及练习/python学习-练习/jichu/directory1
['1.py', '2.py']
['subdir2']
------------------
E:/(network)/python资料及练习/python学习-练习/jichu/directory1/subdir2
['su1.py']
[]
------------------
E:/(network)/python资料及练习/python学习-练习/jichu/me
[]
['mine']
------------------
E:/(network)/python资料及练习/python学习-练习/jichu/me/mine
[]
['you']
------------------
E:/(network)/python资料及练习/python学习-练习/jichu/me/mine/you
[]
[]
------------------
E:/(network)/python资料及练习/python学习-练习/jichu/newpy
[]
[]
------------------
E:/(network)/python资料及练习/python学习-练习/jichu/package1
['module1.py', 'module2.py', '__init__.py']
['__pycache__']
------------------
E:/(network)/python资料及练习/python学习-练习/jichu/package1/__pycache__
['module1.cpython-38.pyc', '__init__.cpython-38.pyc']
[]
------------------
E:/(network)/python资料及练习/python学习-练习/jichu/__pycache__
['calc.cpython-38.pyc', '主程序1.cpython-38.pyc']
[]
------------------
import os
path = os.getcwd()
lis_files = os.walk(path) # 返回为一个元组
print(lis_files) # 是一个迭代器对象 <generator object walk at 0x00000148F96ED7B0>
for dirpath,dirname,filename in lis_files:
for dir in dirname:
print(os.path.join(dirpath,dir)) # 当前目录下有多少个子目录
for file in filename:
print(os.path.join(dirpath,file)) # 遍历指定目录下所有的文件以及目录类似于递归的操作
print('--------------------')
输出结果:
<generator object walk at 0x0000024AD0933740>
E:/(network)/python资料及练习/python学习-练习/jichu/directory1
E:/(network)/python资料及练习/python学习-练习/jichu/me
E:/(network)/python资料及练习/python学习-练习/jichu/newpy
E:/(network)/python资料及练习/python学习-练习/jichu/package1
E:/(network)/python资料及练习/python学习-练习/jichu/__pycache__
E:/(network)/python资料及练习/python学习-练习/jichu/123.txt
E:/(network)/python资料及练习/python学习-练习/jichu/789.jpg
E:/(network)/python资料及练习/python学习-练习/jichu/9810.jpg
E:/(network)/python资料及练习/python学习-练习/jichu/a.txt
E:/(network)/python资料及练习/python学习-练习/jichu/bug.py
E:/(network)/python资料及练习/python学习-练习/jichu/c.txt
E:/(network)/python资料及练习/python学习-练习/jichu/calc.py
E:/(network)/python资料及练习/python学习-练习/jichu/copyphoto.jpg
E:/(network)/python资料及练习/python学习-练习/jichu/d.txt
E:/(network)/python资料及练习/python学习-练习/jichu/demo19.py
E:/(network)/python资料及练习/python学习-练习/jichu/demo3.py
E:/(network)/python资料及练习/python学习-练习/jichu/f.txt
E:/(network)/python资料及练习/python学习-练习/jichu/leiyuduixiang.py
E:/(network)/python资料及练习/python学习-练习/jichu/Object类.py
E:/(network)/python资料及练习/python学习-练习/jichu/os模块.py
E:/(network)/python资料及练习/python学习-练习/jichu/os模块函数.py
E:/(network)/python资料及练习/python学习-练习/jichu/with语句复制图片.py
E:/(network)/python资料及练习/python学习-练习/jichu/上下文管理器.py
E:/(network)/python资料及练习/python学习-练习/jichu/主程序1.py
E:/(network)/python资料及练习/python学习-练习/jichu/主程序2.py
E:/(network)/python资料及练习/python学习-练习/jichu/内置模块.py
E:/(network)/python资料及练习/python学习-练习/jichu/在线安装三方模块使用.py
E:/(network)/python资料及练习/python学习-练习/jichu/多态.py
E:/(network)/python资料及练习/python学习-练习/jichu/引入自定义模块.py
E:/(network)/python资料及练习/python学习-练习/jichu/斐波那契数列.py
E:/(network)/python资料及练习/python学习-练习/jichu/模块.py
E:/(network)/python资料及练习/python学习-练习/jichu/深拷贝与浅拷贝.py
E:/(network)/python资料及练习/python学习-练习/jichu/特殊方法.py
E:/(network)/python资料及练习/python学习-练习/jichu/特殊方法2.py
E:/(network)/python资料及练习/python学习-练习/jichu/生活照10.jpg
E:/(network)/python资料及练习/python学习-练习/jichu/类方法与静态方法.py
E:/(network)/python资料及练习/python学习-练习/jichu/继承.py
E:/(network)/python资料及练习/python学习-练习/jichu/获取.py文件.py
E:/(network)/python资料及练习/python学习-练习/jichu/试试.py
E:/(network)/python资料及练习/python学习-练习/jichu/读写方法.py
E:/(network)/python资料及练习/python学习-练习/jichu/读取文件.py
E:/(network)/python资料及练习/python学习-练习/jichu/调试.py
--------------------
E:/(network)/python资料及练习/python学习-练习/jichu/directory1/subdir2
E:/(network)/python资料及练习/python学习-练习/jichu/directory1/1.py
E:/(network)/python资料及练习/python学习-练习/jichu/directory1/2.py
--------------------
E:/(network)/python资料及练习/python学习-练习/jichu/directory1/subdir2/su1.py
--------------------
E:/(network)/python资料及练习/python学习-练习/jichu/me/mine
--------------------
E:/(network)/python资料及练习/python学习-练习/jichu/me/mine/you
--------------------
--------------------
--------------------
E:/(network)/python资料及练习/python学习-练习/jichu/package1/__pycache__
E:/(network)/python资料及练习/python学习-练习/jichu/package1/module1.py
E:/(network)/python资料及练习/python学习-练习/jichu/package1/module2.py
E:/(network)/python资料及练习/python学习-练习/jichu/package1/__init__.py
--------------------
E:/(network)/python资料及练习/python学习-练习/jichu/package1/__pycache__/module1.cpython-38.pyc
E:/(network)/python资料及练习/python学习-练习/jichu/package1/__pycache__/__init__.cpython-38.pyc
--------------------
E:/(network)/python资料及练习/python学习-练习/jichu/__pycache__/calc.cpython-38.pyc
E:/(network)/python资料及练习/python学习-练习/jichu/__pycache__/主程序1.cpython-38.pyc
--------------------
补充词语理解:
循环(loop),指的是在满足条件的情况下,重复执行同一段代码。比如,while语句。
迭代(iterate),指的是按照某种顺序逐个访问列表中的每一项。比如,for语句。每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值。走n遍,反反复复
遍历(traversal),指的是按照一定的规则访问树形结构中的每个节点,而且每个节点都只访问一次。’走一遍’
递归(recursion),指的是一个函数不断调用自身的行为。比如,以编程方式输出著名的斐波纳契数列。
21 BUG
21.1 bug常见错误
1.漏了末尾的冒号,如if语句,循环语句,else子句等;
2.缩进错误;
3.把英文符号写成中文符号;
4.字符串拼接的时候,把字符串和数字拼在一起;
5.没有定义变量;
6.”==”比较运算符与赋值运算符”=”混用
思路不清导致的问题解决方案
1.使用print()函数;
2.使用”#”暂时注释部分代码;
21.2 bug的常见类型
被动掉坑:程序代码逻辑没有错,只是因为用户错误操作或者一些”例外情况”而导致的程序崩溃;
异常处理机制:可以在异常出现时即时捕获,然后内部继续”消化”,让程序继续运行;
try…except…结构
try:
...
可能会出现的异常的代码...
...
except xxx(异常类型):
...
异常处理代码... # 报错后执行的代码
...
# 输入两个整数并进行除数运算
try:
num1 = int(input('输入第一个整数:'))
num2 = int(input('输入第二个整数:'))
num = num1/num2
print(num)
except:
print('输出错误')
或
try:
num1 = int(input('输入第一个整数:'))
num2 = int(input('输入第二个整数:'))
num = num1/num2
print(num)
except ZeroDivisionError:
print('输出错误')
多个except结构:捕获异常的顺序按照先子类后父亲类的顺序,为了避免遗漏可能出现的异常,可以在最后增加BaseException
try:
...
... # 可能会出现的异常的代码
...
except Expection1:
...
... # 异常处理代码
...
except Expection2:
...
... # 异常处理代码
...
except BaseException:
...
... # 异常处理代码
...
try:
num1 = int(input('输入第一个整数:'))
num2 = int(input('输入第二个整数:'))
num = num1/num2
print(num)
except ZeroDivisionError:
print('除数不能为0')
except ValueError:
print('不能为字母')
except BaseException as e:
print('程序结束')
try…except…else结构
如果try块中没有抛出异常,则执行else块,如果try中抛出异常,则执行except块。
try:
num1 = int(input('输入第一个整数:'))
num2 = int(input('输入第二个整数:'))
num = num1/num2
except BaseException as e:
print('出错了')
print(e)
else:
print('结果为:',num)
try…except…else…finally结构
finally块无论如何是否发生异常都会被执行,能常用来释放try块中申请的资源。
try:
num1 = int(input('输入第一个整数:'))
num2 = int(input('输入第二个整数:'))
num = num1/num2
except BaseException as e:
print('出错了')
print(e)
else:
print('结果为:',num)
finally:
print('无论是否产生异常,总会被执行的代码')
print('程序结束')
输出结果:
输入第一个整数:78
输入第二个整数:2
结果为: 39.0
无论是否产生异常,总会被执行的代码
程序结束
21.2 常见的异常
序号 | 异常类型 | 描述 |
---|---|---|
1 | ZeroDivisionError | 除(或取模)零(所有数据类型) |
2 | IndexError | 序列中没有此索引(index) |
3 | KeyError | 映射中没有这个键 |
4 | NameError | 未声明/初始化对象(没有) |
22 过程note
22.1 python 内置函数sorted()
sorted()函数对所有可迭代对象进行排序操作。
语法:
sorted(interable,cmp=None,key=None,reverse=False)
interable--可迭代对象;
cmp--比较的函数,这个具有两个参数,参数的值都是从可迭代对象中取出,此函数必须遵守的规则是:大于则返回1,小于则返回-1,等于则返回0;
key--主要用来进行比较的元素,只有一个参数,具体的函数参数就是取自可迭代对象中,指定可迭代对象中的一个元素进行排序。
reverse--排序规则,reverse=True降序,reverse=False升序(default).
22.2 sys.argv[]
一个从程序外部获取获取参数的桥梁,获得的是一个列表,用[]提取其中的元素,其第一个元素是程序本身,随后才依次是外部给予的参数。
模块:a_plus_b.py
def plus(a:int, b:int ) -> int:
return a + b
模块:main.py
import sys
from a_plus_b import plus
a = int(sys.argv[1])
b = int(sys.argv[2])
print(plus(a,b))
22.3 内置函数sum()
- sum()方法对序列进行求和计算;
sum(interable[,start])
interable--可迭代对象,列表、元组、集合。
start--指定相加的参数,如果没有设定这个值,默认为0.
22.4 内置函数map()
- map() 会根据提供的函数对指定序列做映射;
map(function,interable,...)
function--函数
interable--一个或多个序列
返回迭代器(python3.x)
import sys
input_filepath = sys.argv[1]
with open(input_filepath,'r',encoding='utf-8') as sum_file:
sumfile = sum_file.read().split(' ')
# print(sumfile,type(sumfile))
new_num = map(int,sumfile)
print(sum(new_num))
22.5 splitlines()方法
- splitlines() 按照(’/r’,’/r/n’,’/n’)分隔,返回一个包含各行作为元素的列表,如果参数keepends为False,不包含换行符,如果为True,则保留换行符。
splitlines()方法语法:
str.splitlines([keepends])
22.6 count()方法
- count()方法用于统计字符串里某个字符或字符串出现的次数,可选参数为在字符串搜索的开始与结束位置。
count()方法语法:
str.count(sub,start = 0,end = len(string))
sub--搜索的子字符串
start--字符串开始搜索的位置。默认为第一个字符,第一个字符的索引值为0。
end--字符串中结束搜索的位置。字符中第一个字符的索引为0。默认为字符串的最后位置
返回值:返回子字符串在字符串中出现的次数。
def num_your(poem):
# write your code here
# num_count = 0
# for item in poem.splitlines():
# if 'your' in item:
# num_count += 1
# return num_count
num_count = poem.count(' your ')
return num_count
22.7 len()方法(内置函数)
-
len()方法返回对象(字符、列表、元组)长度或项目个数。
len()方法语法: len(s) s--对象 返回值:对象长度
22.8 内置函数eval()函数
-
eval()函数用来执行一个字符串表达式,并返回表达式的值。
语法: eval(expression[,globals[,locals]]) expression--表达式 globals--变量作用域,全局命名空间,如果被提供,则必须是一个字典对象。
22.9 requests.post()定义和用法
post()
方法将POST请求发送到指定的URL。
post()
方法将某些数据发送到服务器时使用。
- 语法
requests.post(url, data={key: value}, json={key: value}, args)
args表示下面参数表中的零个或多个*命名*参数。例:
requests.post(url, data = myobj, timeout=2.50)
- 参数值
参数 | 描述 |
---|---|
url | 必须。请求的网址 |
data | 可选。字典,元组列表,字节或要发送到指定URL的文件对象 |
json | 可选。要发送到指定URL的JSON对象 |
files | 可选。要发送到指定URL的文件字典 |
allow_redirects | 可选。用于启用/禁用重定向的布尔值。 默认True (允许重定向) |
auth | 可选。用于启用某种HTTP身份验证的元组。 默认None |
cert | 可选。指定证书文件或密钥的字符串或元组。 默认None |
cookies | 可选。要发送到指定网址的Cookie字典。 默认None |
headers | 可选。要发送到指定网址的HTTP标头字典。 默认None |
proxies | 可选。URL代理协议字典。 默认None |
stream | 可选。如果响应应立即下载(False)或流式传输(True)的布尔指示。 默认False |
timeout | 可选。一个数字或一个元组,指示等待客户端建立连接和/或发送响应的秒数。 默认值None 表示请求将继续,直到连接关闭 |
verify | 可选。用于验证服务器TLS证书的布尔值或字符串指示。 默认True |
原创文章,作者:端木书台,如若转载,请注明出处:https://blog.ytso.com/tech/python/278332.html