python基础版笔记

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  第二行的第一列与第二列
不换行输出--* *
换行输出* *,进行第三行...

输出结果:

1x1=1
2x1=2 2x2=4
3x1=3 3x2=6 3x3=9
4x1=4 4x2=8 4x3=12 4x4=16
5x1=5 5x2=10 5x3=15 5x4=20 5x5=25
6x1=6 6x2=12 6x3=18 6x4=24 6x5=30 6x6=36
7x1=7 7x2=14 7x3=21 7x4=28 7x5=35 7x6=42 7x7=49
8x1=8 8x2=16 8x3=24 8x4=32 8x5=40 8x6=48 8x7=56 8x8=64
9x1=9 9x2=18 9x3=27 9x4=36 9x5=45 9x6=54 9x7=63 9x8=72 9x9=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可重复 无序
集合 可变 不可重复 无序 {}
image-20220424101339229

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

解释:

image-20220424140254120

大小写转换操作的方法:

功能 方法名称 作用
大小写转化 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岁
image-20220427101407941

{}作占位符,

image-20220427101450968
# {}做占位符
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 字符串的编码转化

为什么需要字符串的编解码

image-20220427140209747

编码与解码的方式

编码:将字符串转化为二进制数据(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代表的是二进制数据
输出结果:
天涯共此时
image-20220427143221106

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可以直接用类名调用函数。

image-20220416231159592

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
image-20220416170741364

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>

image-20220417134128185

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"

image-20220417111207656

右键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(外存)

image-20220417152947148

不同的编码格式决定占用的磁盘空间大小。

更改编码格式:

#encoding=gbk
20.8 文件读写的原理__读取磁盘文件中的内容

文件的读写操作俗称“IO操作”;

文件读写操作流程:

image-20220417160235431

操作原理:

image-20220417160445103

.py文件是由解释器去执行,解释器调用操作系统资源操作磁盘上的文件,对硬盘上的文件进行读和写的操作。打开一个python文件后,应用程序的数据运行在内存中,从内存中拿取数据到应用程序叫读,向内存中输出数据叫做写。

内置函数open()创建文件对象

image-20220417161958890

语法规则:

file = open(filename [,mode,encoding])
被创建的文件对象   要创建或打开的文件名称    打开模式默认为只读  默认文本文件txt中字符的编码格式为gbk;
image-20220417162418399
新建文本文档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')称为上下文表达式,对象称为上下文管理器
image-20220417184336604

上下文管理器:一个类对象实现了特殊方法____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()方法:递归遍历指定目录下所有的文件和目录。而且将目录下的子目录都遍历出来。

image-20220418004304630
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
--------------------

image-20220418011504072

补充词语理解:

循环(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的常见类型

被动掉坑:程序代码逻辑没有错,只是因为用户错误操作或者一些"例外情况"而导致的程序崩溃;

异常处理机制:可以在异常出现时即时捕获,然后内部继续"消化",让程序继续运行;

image-20220427164550258

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块中申请的资源

image-20220428164930476
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
posted @ 2022-08-01 23:09  学糕  Views(435)  Comments(0Edit  收藏  举报