python的容器型数据方法实现

list 的相关方法(append,clear,copy,count,extend,index,insert,pop,remove,reverse,sort)

list.append(item) - 在末尾添加指定元素

1
2
3
4
list1 = [1,2,3,4]
item = 5
new_list1 = list1 + [item]
print(new_list1)

list.clear() - 清空列表

1
2
3
list2 = [1,2,3,4]
list2 = []
print(list2)

list.copy() - 产生一个一模一样的新列表

1
2
3
4
5
list3 = [1,2,3,4]
new_list3 = []
for item in list3:
new_list3 += [item]
print(new_list3)

list.count(item) - 获取指定元素在列表中的个数

1
2
3
4
5
6
7
list4 = [1,1,2,1,3,4,3,4]
count = 0
item = 1
for i in list4:
if i == item:
count+=1
print(item,"在list4中出现的次数为",count)

list.extend(序列) - 在列表后面添加一个序列

1
2
3
4
5
list5 = [1,2,3]
list6 = [4,5,6]
for item in list6:
list5+=[item]
print(list5)

list.index(item) - 获取指定元素在列表中第一次出现的下标,元素不存在报错

1
2
3
4
5
6
7
8
9
10
list7 = [5,1,3,4,3]
count = 0
item = 3
for i in list7:
if i == item:
print(count)
break
count += 1
else:
print("错误警告,元素不在列表中")

list.insert(index,item) - 列表指定位置插入指定元素,位置超过列表长度会在末尾追加

1
2
3
4
5
list8 = [1,2,3,4]
index = 2
item = 5
list8 = list8[:index] + [item] + list8[index:]
print(list8)

list.pop(index) - 取出列表指定位置的元素,如果不使用则没有意义,相当于删除操作

如果没有index,默认为列表的最后一个元素

1
2
3
4
5
list9 = [1,2,3,4]
index = 2
aa = list9[index]
list9 = list9[:index] + list9[index+1:]
print(list9)

list.remove(item) - 删除指定元素在列表中出现的第一个,如果元素不存在会报错

1
2
3
4
5
6
7
8
9
10
11
list10 = [1,2,3,4]
item = 3
count = 0
for i in list10:
if i == item:
list10 = list10[:count] + list10[count + 1:]
print(list10)
break
count += 1
else:
print("错误警告,元素不在列表中")

list.reverse() - 将整个列表翻转

1
2
3
list11 = [1,2,3,4]
list11 = list11[::-1]
print(list11)

list.sort() - 对整个列表进行升序排序

1
2
3
4
5
6
7
list12 = [1,3,4,2,1,5,6]
count = len(list12)
for i in range(count):
for j in range(i + 1, count):
if list12[i] > list12[j]:
list12[i], list12[j] = list12[j], list12[i]
print(list12)

dict 相关方法 (clear,copy,get,items,keys,setdefault,update,values,pop,popitem)

dict.clear() - 清空整个字典

1
2
3
dict1 = {'a':10,'b':20,'c':30}
dict1 = {}
print(dict1)

dict.copy() - 产生一个一模一样的新字典

1
2
3
4
5
dict2 = {'a':10,'b':20,'c':30}
new_dict2 = {}
for key in dict2:
new_dict2[key] = dict2[key]
print(new_dict2)

dict.get(key,default=None) - 获取指定键的的值,如果键不存在默认返回None,可以在逗号后面输入指定返回值

1
2
3
4
5
6
7
8
dict3 = {'a':10,'b':20,'c':30}
key1 = 'c'
for key in dict3:
if key == key1:
print(dict3[key1])
break
else:
print(None)

dict.items() - 以列表返回一个视图对象,列表中每一个元素对应字典每一个键值对

1
2
3
4
5
dict3 = {'a':10,'b':20,'c':30}
list1 = []
for key in dict3:
list1.append((key,dict3[key]))
print(list1)

dict.keys() - 以列表返回一个视图对象,列表中每一个元素对应字典每一个键

1
2
3
4
5
dict4 = {'a':10,'b':20,'c':30}
list1 = []
for key in dict4:
list1.append(key)
print(list1)

dict.setdefault(key, default=None) - 和get()类似, 但如果键不存在于字典中,将会添加键并将值设为default

1
2
3
4
5
6
7
8
9
dict5 = {'a':10,'b':20,'c':30}
key1 = 'd'
for key in dict5:
if key == key1:
print(dict5[key1])
break
else:
dict5[key1] = None
print(dict5)

dict.update(dict2) - 把字典dict2的键/值对更新到dict里 - 键相同修改值,键不存在添加键值对

1
2
3
4
5
dict6 = {'a':10,'b':20,'c':30}
dict7 = {'d':40,'c':20}
for key in dict7:
dict6[key] = dict7[key]
print(dict6)

dict.values()

1
2
3
4
5
dict8 = {'a':10,'b':20,'c':30}
list1 = []
for key in dict8:
list1.append(dict8[key])
print(list1)

dict.pop(key) - 删除字典给定键所对应的值,返回值为被删除的值。键值必须给出,键不存在则报错

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
dict9 = {'a':10,'b':20,'c':30}
key1 = 'b'
new_dict9 = {}
count = 0
for key in dict9:
if key == key1:
return_value = dict9[key1]
count+=1
continue
else:
new_dict9[key] = dict9[key]
if count != 0:
print(new_dict9)
else:
print("错误警告,键不存在")

dict.popitem() - 删除字典中的最后一对键和值。

1
2
3
4
5
6
7
8
9
dict9 = {'a':10,'b':20,'c':30}
len_dict9 = len(dict9)-1
new_dict9 = {}
for key in dict9:
new_dict9[key] = dict9[key]
len_dict9-=1
if len_dict9 ==0:
break
print(new_dict9)

tuple 相关方法 (count,index)

tuple.count(item) - 统计指定元素在元组中的个数

1
2
3
4
5
6
7
tuple1 = (1,2,2,3,4)
item = 2
count1 = 0
for i in tuple1:
if i == item:
count1+=1
print(count1)

tuple.index(item) - 获取指定元素在元组中的下标,元素不存在会报错

1
2
3
4
5
6
7
8
9
10
tuple2 = (1,2,3,4,5,2,4)
item = 4
index1 = 0
for i in tuple2:
if item == i:
print("元素的下标是:", index1)
break
index1+=1
else:
print("错误警告,元素不在元组中")

set 方法 (add,clear,copy,difference,difference_update,discradintersection,intersection_update,isdisjoint,issubset,issuperset,pop,remove,union,update,symmetric_differencesymmetric_difference_update)

set.add(元素) - 集合添加元素,如果添加的元素在集合中已存在,则不执行任何操作。

1
2
3
4
set1 = {4,2,5,7}
item = 8
set1 = set1 | {item}
print(set1)

set.update() - 修改当前集合,可以添加新的元素或集合到当前集合中,

##如果添加的元素在集合中已存在,则该元素只会出现一次,重复的会忽略。

1
2
3
4
set1 = {4,2,5,7}
item = 8
set1 = set1 | {item}
print(set1)

add()只可以添加不可变的元素,如数字,字符串,元组,否则报错;

而update()可以添加字符串、列表、元组、字典等可迭代的元素,若添加数字类型会报错。

add()把元素整体性的添加进去,update()会把元素拆分再添加进去。

set.clear() - 移除集合中的所有元素。

1
2
3
set2 = {1,2,3,4}
set2 = set2 & set()
print(set2)

set.copy() - 产生一个一模一样的新集合

1
2
3
4
5
set3 = {5,6,7,8}
set4 = set()
for item in set3:
set4 = set4 | {item}
print(set4)

set.difference(set) - 返回的集合元素包含在第一个集合中,但不包含在第二个集合中

1
2
3
4
set5 = {1,2,3,4,5,6,7}
set6 = {5,6,7,8,9,10,11}
set7 = set5-set6
print(set5,set6,set7)

set.difference_update(set)

1
2
3
4
5
set5 = {1,2,3,4,5,6,7}
set6 = {5,6,7,8,9,10,11}
for item in set6:
set5 -= {item}
print(set5)

difference_update() 方法与 difference() 方法的区别在于

difference() 方法返回一个移除相同元素的新集合,

而 difference_update() 方法是直接在原来的集合中移除元素,没有返回值。

set.discard(value) - 移除指定的集合元素。元素不存在时不会报错

1
2
3
4
5
6
7
set7 = {1,2,3,4,5}
item = 4
for i in set7:
if i == item:
set7 -= {item}
break
print(set7)

set.remove(value) - 移除指定的集合元素。元素不存在时会报错

1
2
3
4
5
6
7
8
9
10
set7 = {1,2,3,4,5}
item = 5
if item in set7:
for i in set7:
if i == item:
set7 -= {item}
print(set7)
break
else:
print("报错,元素不存在集合中")

set.intersection(set1) - 用于返回两个或更多集合中都包含的元素,即交集。

1
2
3
4
set5 = {1,2,3,4,5,6,7}
set6 = {5,6,7,8,9,10,11}
set7 = set5 & set6
print(set7)

set.intersection_update() - 用于获取两个或更多集合中都重叠的元素,即计算交集

1
2
3
4
set5 = {1,2,3,4,5,6,7}
set6 = {5,6,7,8,9,10,11}
set5 &= set6
print(set5)

intersection_update() 方法不同于 intersection() 方法,

因为 intersection()方法是返回一个新的集合,

而intersection_update() 方法是在原始的集合上移除不重叠的元素。

set.isdisjoint() - 判断两个集合是否包含相同的元素,如果没有返回 True,否则返回 False

1
2
3
4
5
6
7
8
9
10
set5 = {1,2,3,4}
set6 = {5,6,7,8,9,10,11}
count = 0
for item in set5:
if item in set6:
count+=1
if count != 0:
print(True)
else:
print(False)

set.issubset() 判断集合的所有元素是否都包含在指定集合中,如果是则返回 True,否则返回 False

1
2
3
4
5
6
7
8
set5 = {5,6,7,8}
set6 = {5,6,7,8,9,10,11}
flag = True
for item in set5:
if item not in set6:
flag = False
break
print(flag)

set.issuperset(set) 判断指定集合的所有元素是否都包含在原始的集合中,如果是则返回 True,否则返回 False。

1
2
3
4
5
6
7
8
set5 = {5,6,7,8}
set6 = {5,6,7,8,9,10,11}
flag = True
for item in set5:
if item not in set6:
flag = False
break
print(flag)

set.symmetric_difference() - 返回两个集合中不重复的元素集合,即会移除两个集合中都存在的元素。

1
2
3
4
set5 = {1,2,3,4,5,6,7,8}
set6 = {5,6,7,8,9,10,11}
set7 = (set5 | set6) - (set5 & set6)
print(set7)

set.symmetric_difference_update() 移除当前集合中在另外一个指定集合相同的元素,并将另外一个指定集合中不同的元素插入到当前集合中。

1
2
3
4
set5 = {1,2,3,4,5,6,7,8}
set6 = {5,6,7,8,9,10,11}
set5 = (set5 | set6) - (set5 & set6)
print(set5)

set.union() - 返回两个集合的并集,即包含了所有集合的元素,重复的元素只会出现一次。

1
2
3
4
set5 = {1,2,3,4,5,6,7,8}
set6 = {5,6,7,8,9,10,11}
set7 = set5 | set6
print(set7)

str 的相关方法

str.capitalize() - 将字符串的第一个字母变成大写,其他字母变小写。

1
2
3
4
5
6
7
8
9
10
str1 = 'wfxMYdfewe'
new_str1 = ''
if 'a' <= str1[0] <= 'z':
new_str1 += chr(ord(str1[0]) - 32)
for index in range(1,len(str1)):
if 'A' <= str1[index] <= 'Z':
new_str1 += chr(ord(str1[index]) + 32)
else:
new_str1 += str1[index]
print(new_str1)

str.center(width,fillchar) - 指定的宽度 width 居中的字符串,fillchar 为填充的字符,默认为空格。

1
2
3
4
5
6
7
8
9
10
11
str2 = 'abcd'
new_str2 = ''
width = 6
if len(str2) >= width:
new_str2 +=str2
else: ### 下面出现的'+'为填充字符可以自定义,默认空格
if (width - len(str2)) % 2:
new_str2 = '+' * ((width - len(str2)) // 2 + 1) + str2 + '+'*((width - len(str2)) // 2)
else:
new_str2 = '+' * ((width - len(str2)) // 2) + str2 + '+' * ((width - len(str2)) // 2)
print(new_str2)

str.count(str1) - 统计字符串里另一个字符串出现的次数

1
2
3
4
5
6
7
8
9
10
str3 = 'ababcd'
str4 = 'bc'
count = 0
if str4 not in str3:
print('0')
else:
for index in range(len(str3)):
if str4 == str3[index:index+len(str4)]:
count+=1
print(count)

str.endswith(str) - 判断字符串是否以指定后缀结尾,如果以指定后缀结尾返回 True,否则返回 False

1
2
3
4
5
6
7
8
9
str4 = 'ababcdc'
str5 = 'c'
if str5 not in str4:
print(False)
else:
if str5 == str4[-len(str5)::1]:
print(True)
else:
print(False)

python对Excel和CSV及PDF操作

1.excel文件的读操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import openpyxl

# 1.加载文件(只能加载后缀是.xlsx文件)

wb = openpyxl.load_workbook('files/小宝剑大药房.xlsx')

# 2.从工作簿中获取工作表相关信息
# 1)获取所有工作表的表名

names = wb.sheetnames
print(names)

# 2)获取活跃表

sheet1 = wb.active
print(sheet1)

# 3)根据表名获取指定表
sheet2 = wb['Sheet1']
print(sheet2)

# 3.从工作表中获取相关内容
# 1)获取表名:工作表对象.title #'Sheet1'
print(sheet1.title)

# 2)获取最大行数
print(sheet1.max_row)

# 3)获取最大列数
print(sheet1.max_column)

# 通过表获取单元格
# 1)获取指定一个单元格
# a.工作表['列号行号'] - 获取指定位置对应单元格(列号是字母)
cell1 = sheet1['B2']
print(cell1)

# b.工作表.cell(行号,列号) - 获取指定位置对应的单元格(列号是数字)
cell2 = sheet1.cell(2,2)

# 2)获取单元格内容
# a.单元格对象.value
print(cell1.value)
print(cell2.value)

# 练习:获取整个表中所有的单元格中的内容

for i in range(1, sheet1.max_row+1):
for j in range(1, sheet1.max_column+1):
cell3 = sheet1.cell(i, j)
print(cell3.value,end=' ')
print()


# 练习:获取第二行所有内容
for j in range(1, sheet1.max_column+1):
cell3 = sheet1.cell(2, j)
print(cell3.value,end=' ')

# 练习:获取第三列所有内容
for i in range(1, sheet1.max_row+1):
cell3 = sheet1.cell(i, 3)
print(cell3.value,end=' ')

2.excel 文件的写操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import openpyxl
import os

# 注意:excel 所有的写操作,如果有效必须在操作完成后对Excel文件对应的工作簿进行保存操作
# 1.新建工作簿
# wb = openpyxl.Workbook()

if os.path.exists('files/test.xlsx'):
print('打开')
wb = openpyxl.load_workbook('files/test.xlsx')
else:
wb = openpyxl.Workbook()
wb.save('files/test.xlsx')


# 2.保存工作簿
# 工作簿对象.save(文件路径)
# wb.save('files/test.xlsx')

# 3.针对表的写操作
# 1)新建表:工作簿对象.create_sheet(表名,位置)
# wb.create_sheet('老师表')
# wb.create_sheet('老师表',0)


# 2)删除表:工作簿最新.remove(表对象)
# try:
# wb.remove(wb['老师表'])
# except:
# pass

# 3)修改表的表名:表对象.title = 新的表名
if 'Sheet' in wb.sheetnames:
wb['Sheet'].title = '课程表'

# wb.save('files/test.xlsx')

# 4.修改单元格中的内容
sheet1 = wb.active
# print(sheet1)
# sheet1['A1'] = '姓名'
# sheet1['B1'] = '年龄'

# sheet1.cell(1,2).value = '姓名'
# wb.save('files/test.xlsx')

# 4.1删除单元格中的内容
# sheet1['B1'] = None
# wb.save('files/test.xlsx')

# 将列表中所有的数据添加到课程表的第3行:['Python', '余婷', '5个月', 10000]

# list1 = ['Python', '余婷','5个月',10000]
# for index, item in enumerate(list1):
# sheet1.cell(3,index+1).value = item
#
# wb.save('files/test.xlsx')

3.csv文件读操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import csv

# 1.创建reader对象
# 1)
# csv.reader(文件对象) - 读数据的时候每一行内容对应一个列表(返回值是包含文件每行内容的迭代器)
# csv.DictReader(文件对象) - 读数据的时候每一行内容对应一个字典(返回值是包含文件每行内容的迭代器)

f = open('files/douyin.csv', encoding='utf-8')

# reader = csv.reader(f)
reader = csv.DictReader(f)

# 2)通过reader读数据
print(next(reader))
print(next(reader))

f.close()


# 4.csv-写数据

'''
# 2.创建文件对应的writer对象
# 1)csv.writer(文件对象)
f = open('files/test1.csv', 'w', encoding='utf-8')
writer = csv.writer(f)

# 写数据:文件对象.writerow(列表)
writer.writerow(['name','age','score','gender'])
writer.writerows([
['小明',18,100,'男'],
['小花',18,100,'女']
])


# 2)csv.DictWriter(文件对象)
f = open('files/test2.csv','w',encoding='utf-8')
writer = csv.DictWriter(f,['name','age','score','gender'])

writer.writeheader()

writer . writerows([
{'name': '小花','age': 30,'score': 92,'gender':'女'},
{'name': '小红','age': 28,'score': 67,'gender':'女'},
{'name': '老王','age': 25,'score': 88,'gender':'男'}
])

f.close()

5.PDF文件操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import PyPDF2

# 5.1 - 读操作 - 获取pdf文件内容
# 1) 以读的方式打开pdf文件
# 创建PDF文件对象 - PyPDF2.PdfFileReader(文件路径)
reader = PyPDF2.PdfFileReader('files/python.pdf')

# 2)获取总的页数
# 文件对象.getNumPages()

total_page = reader.getNumPages()
print(total_page)

# 3)获取指定页面(PageObject的对象)
# 文件对象.getPage(页数)

page0 = reader.getPage(0)
page1 = reader.getPage(1)
page2 = reader.getPage(2)
page3 = page1.rotateClockwise(90)
# page4 = page1.scale(100,200)

# 2写操作

# 1)创建一个空的PDF文件对象
# PyPDF2.PdfFileWriter() - 创建一个空的PDF文件对象
write1 = PyPDF2.PdfFileWriter()

# 2)添加页面
# writer.addPage(页面对象) - 指定页
# writer.addBlankPage() - 添加空白页

write1.addPage(page0)
write1.addBlankPage()
write1.addPage(page1)
write1.addBlankPage()
write1.addPage(page2)
write1.addBlankPage()
write1.addPage(page3)

# 3)保存PDF文件
f = open('files/test.pdf','wb')
write1.write(f)
f.close()

PDF文件添加水印

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import PyPDF2

# 1.准备需要添加水印的PDF
reader = PyPDF2.PdfFileReader('files/存储引擎的讲解.pdf')

# 2.准备水印文件
walter_page = PyPDF2.PdfFileReader('files/water.pdf').getPage(0)

# 3.准备空的PDF,用来存放添加完水印的页

new_pdf = PyPDF2.PdfFileWriter()

for page_num in range(reader.getNumPages()):
# 获取原文件的页面内容
page = reader.getPage(page_num)
# 添加水印
page.mergePage(walter_page)
# 将添加完水印的页加到空白文档中
new_pdf.addPage(page)

# 5.保存新的PDF文件

f = open('files/存储引擎的讲解水印版.pdf','wb')
new_pdf.write(f)
f.close()

6.创建一个水印的PDF文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfgen import canvas

# 1.注册字体文件
pdfmetrics.registerFont(TTFont('Font1','files/Vera.ttf'))
pdfmetrics.registerFont(TTFont('Font2','files/青呱石头体.ttf'))

# 2.生成文字
# 1)创建空的pdf文件

walter_pdf = canvas.Canvas('files/water.pdf')

# 2)设置字体

walter_pdf.setFont('Font1',40)

# 3)设置文字颜色

walter_pdf.setFillColorRGB(1,0,0,1)

# 4)旋转
walter_pdf.rotate(45)

# 5)渲染文字内容

walter_pdf.drawString(400,100,'hello world!')

# 6)保存

walter_pdf.save()

7.Excel文件转CSV文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import openpyxl
import csv

wb = openpyxl.load_workbook('files/小宝剑大药房.xlsx')
sheet1 = wb.active

big_list = []
for i in range(1, sheet1.max_row+1):
list1 = []
for j in range(1, sheet1.max_column+1):
cell3 = sheet1.cell(i, j)
list1.append(cell3.value)

big_list.append(list1)

f = open('files/test3.csv', 'w', encoding='utf-8')
writer = csv.writer(f)
writer.writerows(big_list)
f.close()

8.合并两个PDF文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import PyPDF2

reader1 = PyPDF2.PdfFileReader('files/python.pdf')
reader2 = PyPDF2.PdfFileReader('files/demo1.pdf')
total_page1 = reader1.getNumPages()
total_page2 = reader2.getNumPages()
write1 = PyPDF2.PdfFileWriter()
for i in range(total_page1):
page = reader1.getPage(i)
write1.addPage(page)

for i in range(total_page2):
page = reader2.getPage(i)
write1.addPage(page)

f = open('files/合并python和demo1.pdf','wb')

write1.write(f)
f.close()

python邮件发送

邮件自动发送基本流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# 第一步 smtplib - 登陆邮箱;发送邮件

import smtplib
from email.mime.multipart import MIMEMultipart #邮件对象
from email.header import Header # 头部
from email.mime.text import MIMEText #文本的正文

# 1.连接邮箱服务器
# smtplib.SMTP_SSL(服务器地址,邮箱服务端口) - 连接邮箱服务器并且返回一个连接对象

connect = smtplib.SMTP_SSL('smtp.qq.com',465)

# 2.登陆邮箱
# 连接对象.login(邮箱地址,密码(授权码))

connect.login('QQ号@qq.com','授权码')

# 第二步 - 准备邮件
# 1.创建一个邮件对象

email = MIMEMultipart()

# 2.设置邮件主题
# Header(邮件标题,编码方式)

email['Subject'] = Header('第一次普通邮件发送','utf-8').encode()

# 3.设置邮件接收者信息(收件人)

email['To'] = 'QQ号@qq.com'

# 4.设置邮件发件人

email['From'] = 'QQ号@qq.com <QQ号@qq.com>'

# 5.添加正文
'''
MIMEText(文字内容,类型,编码方式)
类型 - plain(普通文字),html(超文本)
'''

text = MIMEText('hello world','plain','utf-8')
email.attach(text)

# 第三步:通过连接发送邮件
# 连接对象.sendmail(发件人,收件人,邮件对象.as_string())

connect.sendmail('QQ号@qq.com','QQ号@qq.com',email.as_string())
connect.quit()

发送包含附件的邮件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import smtplib
from email.mime.multipart import MIMEMultipart #邮件对象
from email.header import Header # 头部
from email.mime.text import MIMEText #文本的正文
from email.mime.image import MIMEImage

# 登陆
connect = smtplib.SMTP_SSL('smtp.qq.com',465)
connect.login('QQ号@qq.com','授权码')

# 准备邮件

email = MIMEMultipart()

email['Subject'] = Header('第二次邮件发送带附件','utf-8').encode()
email['To'] = 'QQ号@qq.com'
email['From'] = 'QQ号@qq.com <QQ号@qq.com>'

text = MIMEText('照片在附件中,请注意查收','plain','utf-8')
email.attach(text)

# 准备图片

# 打开图片读取图片二进制数据
image_data = open('image/小猫.jpg', 'rb').read()

# 创建图片对象
image = MIMEImage(image_data)

# 设置图片为附件
image["Content-Disposition"] = 'attachment;filename="cat.jpg"'

# 将图片添加到邮件对象中
email.attach(image)

# ===============2.其他文件附件================

file_data1 = open('image/2021年“专升本”学生收费公示栏.xls',"rb").read()
file1 = MIMEText('file_data1', 'base64', 'utf-8')
file1['Content-Disposition'] = ' attachment; filename="a.xls"'
email.attach(file1)

file_data2 = open('image/邱少云烈士纪念馆.pptx','rb').read()
file2 = MIMEText('file_data1', 'base64', 'utf-8')
file2['Content-Disposition'] = ' attachment; filename= "b.pptx"'
email.attach(file2)

# 发送邮件
connect.sendmail('QQ号@qq.com','QQ号@qq.com',email.as_string())
connect.quit()

发送超文本文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import smtplib
from email.mime.multipart import MIMEMultipart #邮件对象
from email.header import Header # 头部
from email.mime.text import MIMEText
from email.mime.image import MIMEImage

# 登陆
connect = smtplib.SMTP_SSL('smtp.qq.com',465)
connect.login('QQ号@qq.com','授权码')

# 准备邮件

email = MIMEMultipart()

email['Subject'] = Header('第三次发送html邮件','utf-8').encode()
email['To'] = 'QQ号@qq.com'
email['From'] = 'QQ号@qq.com <QQ号@qq.com>'

#====================邮件正文===========================

content = open('test.html',encoding='utf-8').read()
text = MIMEText(content,'html', 'utf-8')
email.attach(text)


image_data = open('image/aa.jpg', 'rb').read()
image = MIMEImage(image_data)
image.add_header("Content-ID",'<image1>')
email.attach(image)

connect.sendmail('QQ号@qq.com','QQ号@qq.com',email.as_string())
connect.quit()

图片批量发送

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import smtplib
from email.mime.multipart import MIMEMultipart
from email.header import Header
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
import os

connect = smtplib.SMTP_SSL('smtp.qq.com', 465)
connect.login('QQ号@qq.com', '授权码')

email = MIMEMultipart()
email['Subject'] = Header('第四次图片批量发送邮件', 'utf-8').encode()
email['To'] = 'QQ号@qq.com'
email['From'] = 'QQ号@qq.com <QQ号@qq.com>'

# ========================邮件正文=====================
all_images = os.listdir('images')
ids = []
for name in all_images:
image_data = open(f'images/{name}', 'rb').read()
image = MIMEImage(image_data)
cid = name.split(".")[0]
ids.append(cid)
image.add_header('Content-ID', f'<{cid}>')
email.attach(image)

send = ''
for cid in ids:
send += f'<img src="cid:{cid}" alt=""><br>'
text = MIMEText(send, 'html', 'utf-8')
email.attach(text)


connect.sendmail('QQ号@qq.com', 'QQ号@qq.com', email.as_string())
connect.quit()

作业

将指定文件夹中的所有文件作为附件发送

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import os
import smtplib
from email.mime.multipart import MIMEMultipart #邮件对象
from email.header import Header # 头部
from email.mime.text import MIMEText #文本的正文

# 登陆
connect = smtplib.SMTP_SSL('smtp.qq.com',465)
connect.login('QQ号@qq.com','授权码')

# 准备邮件

email = MIMEMultipart()

email['Subject'] = Header('作业批量发送附件','utf-8').encode()
email['To'] = 'QQ号@qq.com'
email['From'] = 'QQ号@qq.com <QQ号@qq.com>'

text = MIMEText('对方发送了大量附件,请注意查收','plain','utf-8')
email.attach(text)

# ===============批量文件附件================

all_fujian = os.listdir('fujian')
for name in all_fujian:
fujian_data = open(f'fujian/{name}', 'rb').read()
fujian = MIMEText('fujian_data','base64','utf-8')
cid = name.split(".")[0]
fujian['Content-Disposition'] = f'attachment; filename="{cid}.txt"'
email.attach(fujian)

# 发送邮件
connect.sendmail('QQ号@qq.com','QQ号@qq.com',email.as_string())
connect.quit()

函数对象的操作

对象属性的增删改查

1
2
3
4
5
6
7
8
9
10
11
12
13
class Students:
def __init__(self,name,age,score):
self.name = name
self.age = age
self.score = score

# 在当前类的对象被打印的时候自动调用,并将这个方法的返回值作为打印结果(返回值必须是字符串)
def __repr__(self):
return str(self.__dict__)
# __dict__ 直接返回当前对象的所有属性和值,以字典的键值对的形式提供

stu1 = Students('小明',18,90)
stu2 = Students('张三',19,80)

1.查 - 获取属性值

1
2
3
1)对象.属性 - 获取对象指定属性的值(属性不存在报错)
2)getattr(对象,属性名) - 获取对象指定属性的值(属性不存在报错)
2)getattr(对象,属性名,默认值) - 获取对象指定属性的值(属性不存在,返回默认值)
1
2
3
4
5
6
print(stu1.name)
print(getattr(stu1,'name'))

# print(stu1.gender) # AttributeError: 'Student' object has no attribute 'gender'
# print(getattr(stu1,'gender')) # AttributeError: 'Student' object has no attribute ' gender '
print(getattr(stu1,'gender', '男')) #男

2.增,改

1
2
1)对象.属性 = 值 - 当属性存在时修改属性的值,属性不存在时候添加属性并赋值
2)setattr(对象,属性名,值) - 当属性存在时修改属性的值,属性不存在时候添加属性并赋值
1
2
3
4
5
6
stu1.name = "小黄"
print(stu1,stu2,sep='\n')

stu1.sex = "男"
stu2.sex = "女"
print(stu1,stu2,sep='\n')

3. 删

1
2
3
1)del 对象.属性 - 删除指定对象的指定属性
2)del 对象 - 删除指定对象
3)delattr(对象,属性名) - 删除指定对象的指定属性
1
2
3
del stu1.score
del stu2.score
print(stu1,stu2,sep='\n')

slots # 约束当前类可以拥有的对象属性

1
2
3
4
5
6
7
8
9
class A:
# __slots__ 属性值就是当前类的对象最多能够拥有的对象属性,为空的时候,这个类不能有对象属性
__slots__ = ('x','y','z') # 约束当前类可以拥有的对象属性

# 如果当前类使用了__slots__,那么这个类的对象就不能在使用__dict__属性

def __init__(self,x,y):
self.x = x
self.y = y

类属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
## 1. 类.__doc__  - 获取类的说明文档

print(int.__doc__)
print(int(10).bit_length()) # 获取对象的二进制位数
# print(dict.__doc__)

## 2.类.__module__ - 获取类所在的模块(类属性)

print(int.__module__)

## 3.对象.__class__ - 获取对象的类型,功能和type(对象)一样

class A:
pass

a = A()
print(a.__class__)
print(type(a))

## 4.1 类.__dict__ - 获取类所有的类属性和对应的值,以字典的形式返回
## 4.2 对象.__dict__ - 获取对象所有的对象属性和对应的值,以字典的形式返回

print(A.__dict__)
print(a.__dict__)

## 5. 类.__name__ - 获取类的名字(类属性)

print(A.__name__)

## 6.1 __base__ - 获取当前类的父类
## 6.2 __bases__ - 获取当前类的所有父类

print(A.__base__)

运算符重载

1
2
3
4
5
6
7
8
9
10
11
12
from copy import copy

print(10 + 29)
print('abc' + '34')
print([10, 34] + [239, 0, 'abc'])

print(10 - 9)
print({23, 89} - {23})


# 10 + 29 == 10.__add__(29)
# 'abc' + '34' == 'abc'.__add__('34')

1. python中的运算符

1
2
python中每个运算符都对应一个固定的魔法方法,哪个类型中实现的对应的魔法方法,那个类型的数据就支持对应的运算符。
(python中某种数据是否支持某种运算符就看这个类中是否定义了运算符对应的魔法方法)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class Student:
def __init__(self, name, age):
self.name = name
self.age = age

# self + other
def __add__(self, other):
return self.age + other.age

# self * other
def __mul__(self, other):
return [copy(self) for _ in range(other)]

# self > other
def __gt__(self, other):
return self.age > other.age

def __repr__(self):
return f'<{str(self.__dict__)[1:-1]}, id: {id(self)}>'
# return str(self.__dict__)


stu1 = Student('小明', 18)
stu2 = Student('小花', 20)

a = stu1 + stu2 # a = stu1.__add__(stu2)
print(a)
print(stu1 * 4)

# print(stu1 in stu2)

stu_list = [stu1, stu2, Student('张三', 12)]
print(stu_list)

# print(max(stu_list, key=lambda item: item.age))
print(max(stu_list))

1. 继承

1
2
3
继承就是让子类直接拥有父类的属性和方法。
子类 - 继承者
父类 - 被继承者,又叫超类

2. 继承的语法

1
2
3
4
5
6
7
8
9
10
11
class 类名(父类):
说明文档
类的内容


class 类名(父类1, 父类2,...):
说明文档
类的内容

注意:如果定义类的时候没有写继承关系,那么这个类默认继承基类object
class 类名: == class 类名(object):

3.添加新属性和方法

1
2
3
4
1)添加方法和添加类属性
直接在子类中定义新的类属性和方法

2)添加对象属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
class Person:
num = 61

def __init__(self):
self.name = '张三'
self.age = 30
self.gender = '男'

def eat(self, food):
print(f'在吃{food}')

@staticmethod
def func1():
print('静态方法')


class Student(Person):
x = '学生'

def __init__(self):
# 调用当前类的父类的__init__方法
super().__init__()
self.study_id = '0001'
self.subject = 'Python'

def study(self):
print('好好学习,天天向上!')

@classmethod
def func2(cls):
print('学生的类方法')


stu = Student()
print(stu.name, stu.age, stu.gender)
stu.eat('包子')

print(Student.num)
Student.func1()

print(Student.x)
stu.study()
Student.func2()
print(stu.study_id, stu.subject)


class A:
def __init__(self, x, y):
self.x = x
self.y = y


class B(A):
def __init__(self, m, n, x=10, y=20):
super().__init__(x, y)
self.m = m
self.n = n


a = A(200, 300)

b = B(1, 2)
print(b.x, b.y)
# b.x = 3
# b.y = 4

1. 子类和父类有相同的方法(重写)

1
2
3
4
5
6
7
8
9
10
11
12
class A:
def func1(self):
print('A的func1')


class B(A):
def func1(self):
print('B的func1')


B().func1()
A().func1()

2. super的用法

1
2
super(类, 对象).方法()   -  调用指定类的父类的指定方法
注意:()中的对象必须是()里面类的对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class A:
def func1(self):
print('A的func1')


class B(A):
def func2(self):
super(B, self).func1()
print('B的func2')


B().func2()


print('-------------------------------------------------')
class A:
def func1(self):
print('A的func1')

def func2(self):
print('A的func2')


class B(A):
def func1(self):
print('B的func1')


class C:
def func1(self):
print('C的func1')


class D(C):
def func1(self):
super(B, B()).func2()
print('D的func1')


d = D()
d.func1()

3.多继承: 子类只能继承第一个父类的对象属性(方法和类属性都可以继承)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class AA:
num = 100

def __init__(self):
self.x = 100
self.y = 200

def func1(self):
print('对象方法AA')


class BB:
message = '你好'

def __init__(self):
self.m = 100
self.n = 200

def func2(self):
print('对象方法BB')


class CC(AA, BB):
pass


c = CC()

print(CC.num, CC.message)

c.func1()
c.func2()

print(c.x, c.y)
# print(c.m, c.n) # AttributeError: 'CC' object has no attribute 'm'

4. 私有化

1
2
3
4
5
6
7
8
9
10
访问权限(属性和方法的权限):公开的、保护的、私有的
公开的 - 在类的外部可以使用、类的内部可以使用、也可以被继承
保护的 - 在类的外部不可以使用、类的内部可以使用、也可以被继承
私有的 - 只能在类的内部使用,不能被继承,也不能在外部使用

python中类的内容的权限只有一种:公开的
python的私有化: 想让属性和方法变成私有的只需要在名字前加__(但是不能同时用__结尾)
python私有化的本质:就存储数据的时候在私有化名字前加 '_类名'

python中的保护:在名字前加_
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class A:
m = 100
__n = 200

@staticmethod
def func1():
print(A.m, A.__n)
A.__func2()

@staticmethod
def __func2():
print('私有方法')


print(A.m)
A.func1()

# print(A.__n)
# A.__func2()

print(A._A__n)
# python之禅

1. 拷贝

1
2
3
4
5
6
7
8
9
10
1)直接赋值
直接将变量中的地址赋值给另外一个变量,赋值后两个变量指向同一块内存区域,并且相互影响

2)浅拷贝
列表切片、列表.copy()、字典.copy()等都是浅拷贝、copy()
复制原数据产生一个新的数据,将新的数据的地址返回。如果原数据中有子对象(有可变数据),不会复制子对象

3)深拷贝
deepcopy
复制原数据产生一个新的数据,将新的数据的地址返回。如果原数据中有子对象,子对象也会被复制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
from copy import copy,deepcopy
class Dog:
def __init__(self, name, gender='公'):
self.name = name
self.gender = gender

def __repr__(self):
return str(self.__dict__)


class Person:
def __init__(self, name, age=18, dog=None):
self.name = name
self.age = age
self.dog = dog

def __repr__(self):
return str(self.__dict__)


p1 = Person('小明', dog=Dog('财财'))
p2 = p1
p3 = copy(p1)
p4 = deepcopy(p1)

print(f'p1:{p1}, id:{id(p1)}')
print(f'p2:{p2}, id:{id(p2)}')
print(f'p3:{p3}, id:{id(p3)}')
print(f'p4:{p4}, id:{id(p4)}')
print('-------------------------------------------------')
p1.name = '小花'
p1.dog.name = '大黄'
print(f'p1:{p1}, id:{id(p1)}')
print(f'p2:{p2}, id:{id(p2)}')
print(f'p3:{p3}, id:{id(p3)}')
print(f'p4:{p4}, id:{id(p4)}')

2. 内存管理

1
2
3
4
5
6
7
1)内存的申请
定义变量保存数据的时候系统会自动申请。如果定义变量保存的时候可变数据,每次都会申请新的内存,如果是不可变的数据,会检查这个数据
是否已经保存过,如果已经存储就不会再重新申请内存。

2)释放
如果一个数据的引用计数(引用的个数)为0,那么这个数据就会被自动释放。
引用:保存数据地址的对象就是这个数据的引用

面向对象进阶

编程思想:面向过程编程,函数式编程,面向对象编程

1
函数式编程
1
2
3
4
5
6
7
def jiecheng(k:int):
cheng = 1
for item in range(1,k+1):
cheng *= item
return cheng

print(jiecheng(10))

1.什么是类,什么是对象

1
2
类:拥有相同功能和相同属性的对象的集合
对象:对象是类的实例

2.创建类和创建对象

1
创建类: - 就是用代码描述清楚这个类是拥有哪些相同功能(函数)和属性(变量)的对象的集合
1
2
3
4
5
6
7
8
9
10
11
12
13
1)语法:
class 类名:
类的说明文档
类的内容

类名-见名知意,标识符,驼峰式命名,首字母大写,不使用系统的函数名,类名,模块名
类的内容 - 包含属性和方法
属性:类属性(类的字段),对象属性
方法:对象方法,类方法,静态方法

2)创建对象
语法:类名()

1
2
3
4
5
6
7
8
9
10
### 创建类
class Person:
# 属性
# 方法
def eat(self):
print("干饭")


### 创建对象
p1 = Person()

1.对象方法

1
2
3
4
5
6
7
1)怎么定义
直接定义在类中的函数 - 对象方法
2)怎么调用
通过"对象."的形式来调用
3)特点
有默认参数self,这个参数在函数调用时不需要传参,系统会自动将当前对象传给self(谁调用就指向谁)

1
2
3
4
5
6
7
8
9
10
11
12
class Student:
def study(self):
print(f'self:{self}')
print("学习") # study是一个对象方法

def eat(self,food):
print(f'吃{food}')

stu1 = Student() # stu1是一个对象
stu1.study() #调用对象方法
print(f'stu1:{stu1}')
stu1.eat("牛肉") # 调用对象方法

1. __init__方法 - 初始化方法

1
2
3
4
5
6
7
8
9
10
11
1)构造方法:函数名和类名相同,用来创建对象的函数就是构造函数-构造方法
python的构造函数,在创建类的时候系统会自动创建这个类的构造函数

2)初始化方法:
a.通过类创建对象的时候系统会自动调用__init__方法
b.在调用构造函数创建对象的时候,需不需要参数需要看对应的__init__除了self以外
有没有额外的参数,有几个参数
c.程序员在类中添加__init__方法的时候只需要保证方法名是__init__有默认参数self就可以
形参和函数体可以根据情况来添加

补充:方法名前后都有两个下划线的方法又叫魔法方法,这类方法在特定情况下被自动调用,不需要程序员主动调用
1
2
3
4
5
class Dog:
def __init__(self):
print("初始化方法") # 通过类创建对象的时候自动调用

p1 = Dog()

1.属性

1
2
3
4
5
6
7
8
9
10
11
12
13
1)类属性
a.怎么定义:直接定义在类中的变量
b.怎么使用:通过"类.变量名"的方式来使用
c.什么时候用:属性值不会因为对象不同而不一样



2)对象属性
a.怎么定义:
"self.属性名 = 值" 的形式定义在__init__方法中
b.怎么使用
"对象."的方式来使用
c.什么时候用
1
2
3
4
5
6
7
8
9
10
11
12
class Circle:
pi = 3.1415926 # pi就是一个类属性

def __init__(self):
self.radius = 1 #radius就是一个对象属性

# 使用类属性
print(Circle.pi)

# 使用对象属性
c1 = Circle()
print(c1.radius)

2.对象属性的初始值

1
2
3
4
5
6
7
8
9
10
11
12
13
class Person:
def __init__(self,name,gender='男'):
self.name = name
self.gender = gender
self.age = 0

p1 = Person('小明')
p2 = Person('张三')
p3 = Person('小花','女')

print(p1.name,p1.gender)
print(p2.name,p2.gender)
print(p3.name,p3.gender)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Circle:
pi = 3.1415926 # pi就是一个类属性

def __init__(self,radius):
self.radius = radius #radius就是一个对象属性

def area(self):
# 如果在实现对象方法的功能时候需要用到对象属性,由self来提供
return Circle.pi * self.radius ** 2

def perimeter(self):
return Circle.pi * self.radius * 2

c1 = Circle(2)
c2 = Circle(4)

print(c1.area())
print(c2.area())

print(c1.perimeter())
print(c2.perimeter())

方法 - 定义在类中的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1.对象方法
a.怎么定义 - 直接定义在类中
b.怎么调用 - 对象.
c.特点 - 有个默认参数self,self不用传参,谁调用self就指向谁
d.什么时候用 - 如果实现函数的功能需要用到对象属性,就定义成对象方法

2.类方法
a.怎么定义 - 定义函数前加装饰器 @classmethod
b.怎么调用 - 类.
c.特点 - 有个默认参数cls,调用时不用传参,系统自动将当前类传给cls
d.什么时候用 - 在不需要对象属性的前提下

3.静态方法
a.怎么定义 - 定义函数前加装饰器 @staticmethod
b.怎么调用 - 类.
c.特点 - 没有默认参数
d.什么时候用 - 在不需要对象属性的前提下,也不需要类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class A:

def func1(self):
print("对象方法")

@classmethod
def func2(cls):
print("类方法")
print(f'cls:{cls}')

@staticmethod
def func3():
print("静态方法")

a = A()
a.func1()

print(f'A:{A}')
A.func2()

A.func3()

作业

1. 定义一个狗类和一个人类:狗拥有属性:姓名、性别和品种 拥有方法:叫唤,人类拥有属性:姓名、年龄、狗 拥有方法:遛狗

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Dog:

def __init__(self,name,sex,variety):
self.name = name
self.sex = sex
self.variety = variety

@classmethod
def cry_out(cls):
print("叫唤")


dog1 = Dog('小白','母狗','阿拉斯加')
print(dog1.name,dog1.sex,dog1.variety)
Dog.cry_out()

class Person:

def __init__(self, name, age, dog):
self.name = name
self.age = age
self.dog = dog

@classmethod
def walk_the_dog(self):
print("遛狗")

p1 = Person("小明",'18','小白')
print(p1.name,p1.age,p1.dog)
Person.walk_the_dog()

2. 定义一个矩形类,拥有属性:长、宽 拥有方法:求周长、求面积

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Rectangle:
def __init__(self,length,width):
self.length = length
self.width = width

def area(self):
return self.length * self.width

def perimeter(self):
return self.length * 2 + self.width * 2

r1 = Rectangle(2,3)

print(f'r1的面积是{r1.area()}周长是{r1.perimeter()}')

3. 定义一个二维点类,拥有属性:x坐标、y坐标 拥有方法:求当前点到另外一个点的距离

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
"""方法1"""
class TwoDimensionalPoint:
def __init__(self,x,y):
self.x = x
self.y = y

def distance(self,x,y):
return ((self.x - x) ** 2 + (self.y - y) ** 2) ** 0.5

P1 = TwoDimensionalPoint(0,0)

print(P1.distance(1,2))

"""方法2"""
class TwoDimensionalPoint:
def __init__(self,x,y):
self.x = x
self.y = y

def distance(self,other):
return ((self.x - other.x) ** 2 + (self.y - other.y) ** 2) ** 0.5

P1 = TwoDimensionalPoint(0,0)
P2 = TwoDimensionalPoint(1,2)
print(P1.distance(P2))

4. 定义一个圆类,拥有属性:半径、圆心 拥有方法:求圆的周长和面积、判断当前圆和另一个圆是否外切

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Circle:
pi = 3.14
def __init__(self,radius,center=None):
self.radius = radius
self.center = center


def area(self):
return Circle.pi * self.radius ** 2

def perimeter(self):
return Circle.pi * self.radius * 2

def external(self,other):
P = ((self.center[0] - other.center[0])**2 + (self.center[1] - other.center[1])**2) ** 0.5
if P == self.radius + other.radius:
return '是外切'
else:
return "不是外切"

C1 = Circle(3)
print(f'圆C1的面积是{C1.area()}周长是{C1.perimeter()}')

C1 = Circle(3,(1,2))
C2 = Circle(6,(5,6))

print(C1.external(C2))

5. 定义一个线段类,拥有属性:起点和终点, 拥有方法:获取线段的长度

1
2
3
4
5
6
7
8
9
10
11
class Segment:
def __init__(self,begin,end):
self.begin = begin
self.end = end

def length(self):
return ((self.begin[0] - self.end[0])**2 + (self.begin[1] - self.end[1])**2) ** 0.5

S1 = Segment((0,0),(3,4))

print(S1.length())

面向对象

  1. 定义一个狗类和一个人类:

    狗拥有属性:姓名、性别和品种 拥有方法:叫唤

    人类拥有属性:姓名、年龄、狗 拥有方法:遛狗

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    class Dog:

    def __init__(self,name,sex,variety):
    self.name = name
    self.sex = sex
    self.variety = variety

    @classmethod
    def cry_out(cls):
    print("叫唤")


    dog1 = Dog('小白','母狗','阿拉斯加')
    print(dog1.name,dog1.sex,dog1.variety)
    Dog.cry_out()

    class Person:

    def __init__(self, name, age, dog):
    self.name = name
    self.age = age
    self.dog = dog

    @classmethod
    def walk_the_dog(self):
    print("遛狗")

    p1 = Person("小明",'18','小白')
    print(p1.name,p1.age,p1.dog)
    Person.walk_the_dog()
  2. 定义一个矩形类,拥有属性:长、宽 拥有方法:求周长、求面积

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class Rectangle:
    def __init__(self,length,width):
    self.length = length
    self.width = width

    def area(self):
    return self.length * self.width

    def perimeter(self):
    return self.length * 2 + self.width * 2

    r1 = Rectangle(2,3)

    print(f'r1的面积是{r1.area()}周长是{r1.perimeter()}')
  3. 定义一个二维点类,拥有属性:x坐标、y坐标 拥有方法:求当前点到另外一个点的距离

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    """方法1"""
    class TwoDimensionalPoint:
    def __init__(self,x,y):
    self.x = x
    self.y = y

    def distance(self,x,y):
    return ((self.x - x) ** 2 + (self.y - y) ** 2) ** 0.5

    P1 = TwoDimensionalPoint(0,0)

    print(P1.distance(1,2))

    """方法2"""
    class TwoDimensionalPoint:
    def __init__(self,x,y):
    self.x = x
    self.y = y

    def distance(self,other):
    return ((self.x - other.x) ** 2 + (self.y - other.y) ** 2) ** 0.5

    P1 = TwoDimensionalPoint(0,0)
    P2 = TwoDimensionalPoint(1,2)
    print(P1.distance(P2))
  4. 定义一个圆类,拥有属性:半径、圆心 拥有方法:求圆的周长和面积、判断当前圆和另一个圆是否外切

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    class Circle:
    pi = 3.14
    def __init__(self,radius,center=None):
    self.radius = radius
    self.center = center


    def area(self):
    return Circle.pi * self.radius ** 2

    def perimeter(self):
    return Circle.pi * self.radius * 2

    def external(self,other):
    P = ((self.center[0] - other.center[0])**2 + (self.center[1] - other.center[1])**2) ** 0.5
    if P == self.radius + other.radius:
    return '是外切'
    else:
    return "不是外切"

    C1 = Circle(3)
    print(f'圆C1的面积是{C1.area()}周长是{C1.perimeter()}')

    C1 = Circle(3,(1,2))
    C2 = Circle(6,(5,6))

    print(C1.external(C2))
  5. 定义一个线段类,拥有属性:起点和终点, 拥有方法:获取线段的长度

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class Segment:
    def __init__(self,begin,end):
    self.begin = begin
    self.end = end

    def length(self):
    return ((self.begin[0] - self.end[0])**2 + (self.begin[1] - self.end[1])**2) ** 0.5

    S1 = Segment((0,0),(3,4))

    print(S1.length())

正则表达式练习

利用正则表达式完成下面的操作:

一、不定项选择题

  1. 能够完全匹配字符串"(010)-62661617"和字符串"01062661617"的正则表达式包括( A,B,D)

A. r"\(?\d{3}\)?-?\d{8}"
B. r"[0-9()-]+"
C.r"[0-9(-)]*\d*"
D.r"[(]?\d*[)-]*\d*"

  1. 能够完全匹配字符串“back”和“back-end”的正则表达式包括( A,B,C,D)
    A. r“\w{4}-\w{3}|\w{4}”
    B. r“\w{4}|\w{4}-\w{3}”
    C.r “\S+-\S+|\S+”
    D. r“\w\b-\b\w|\w*”

  2. 能够完全匹配字符串“go go”和“kitty kitty”,但不能完全匹配“go kitty”的正则表达式包括(A,D)
    A.r “\b(\w+)\b\s+\1\b”
    B. r“\w{2,5}\s*\1”
    C. r“(\S+) \s+\1”
    D. r“(\S{2,5})\s{1,}\1”

  3. 能够在字符串中匹配“aab”,而不能匹配“aaab”和“aaaab”的正则表达式包括(B,C )
    A. r“a*?b”
    B. r“a{,2}b”
    C. r“aa??b”
    D. r“aaa??b”

二、编程题

1.用户名匹配

​ 要求: 1.用户名只能包含数字 字母 下划线

​ 2.不能以数字开头

​ 3.⻓度在 6 到 16 位范围内

1
2
3
4
5
while True:
from re import fullmatch
username = input("请输入用户名:")
if fullmatch(r'[_a-zA-Z][_a-zA-Z0-9]{5,15}',username) != None:
break
  1. 密码匹配

​ 要求: 1.不能包含!@#¥%^&*这些特殊符号

​ 2.必须以字母开头

​ 3.⻓度在 6 到 12 位范围内

1
2
3
4
5
while True:
from re import fullmatch
key = input("请输入密码:")
if fullmatch(r'[a-zA-Z][^!@#¥%^&*]{5,11}',key) != None:
break
  1. ipv4 格式的 ip 地址匹配
    提示: IP地址的范围是 0.0.0.0 - 255.255.255.255
1
2
3
4
5
while True:
from re import fullmatch
ipv4 = input("请输入ip地址:")
if fullmatch(r'((\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])',ipv4) != None:
break
  1. 提取用户输入数据中的数值 (数值包括正负数 还包括整数和小数在内) 并求和
1
例如:“-3.14good87nice19bye” =====> -3.14 + 87 + 19 = 102.86
1
2
3
4
5
from re import *
from functools import reduce
result = findall(r'-?\d+\.?\d*','-3.14good87nice19bye')
print(sum(eval(item) for item in result))
print(reduce(lambda x,y:x+eval(y),result,0))
  1. 验证输入内容只能是汉字

    1
    2
    3
    4
    5
    while True:
    from re import fullmatch
    content = input("请输入内容:")
    if fullmatch(r'[\u4e00-\u9fa5]+',content) != None:
    break
  2. 匹配整数或者小数(包括正数和负数)

    1
    2
    3
    4
    5
    while True:
    from re import fullmatch
    nums = input("请输入数字:")
    if fullmatch(r'([-+]?[1-9]\d*|0)(\.\d+)?',nums) != None:
    break
  3. 验证输入用户名和QQ号是否有效并给出对应的提示信息

    要求:
    用户名必须由字母、数字或下划线构成且长度在620个字符之间
    QQ号是5
    12的数字且首位不能为0

    1
    2
    3
    4
    5
    while True:
    from re import fullmatch
    nums = input("请输入qq号:")
    if fullmatch(r'[1-9]\d{4,14}',nums) != None:
    break
  4. 拆分长字符串:将一首诗的中的每一句话分别取出来

    ​ poem = ‘窗前明月光,疑是地上霜。举头望明月,低头思故乡。’

    1
    2
    3
    4
    from re import *
    poem = '窗前明月光,疑是地上霜。举头望明月,低头思故乡。'
    result = split(r'[,。]',poem)
    print(result)

正则表达式

1.正则表达式

1
2
3
re 模块是python提供的专门用来支持正则表达式的模块
fullmatch函数:
fullmatch(正则表达式,字符串) - 让正则表达式和指定

2.正则语法

1
2
3
4
5
正则表达式 - 正则表达式是一个让字符串复杂问题的变得简单的工具
写正则表达式的主要工作,用正则符号描述清楚相关字符串的规则

python正则比表示方式:r'正则表达式'
js的正则:/正则表达式/
1
2
3
4
5
6
7
8
9
10
1) 普通字符(普通符号)
在正则除了有特殊功能或者特殊意义以外的符号;
普通字符在正则中表示这个符号本身。

# 匹配一个字符串有三个字符分别是a、b和c

from re import fullmatch

re_str = r'abc'
print(fullmatch(re_str, 'abc'))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2) .  -  匹配任意一个字符
注意:一个.只能匹配一个任意字符

# 匹配一个字符,长度是三,第一个字符是a,最后一个字符是c,a和c之间是任意一个字符
re_str = r'a.c'
print(fullmatch(re_str, 'abc'))
print(fullmatch(re_str, 'a+c'))
print(fullmatch(re_str, 'a好c'))

re_str = r'abc...'
print(fullmatch(re_str, 'abcm./'))
print(fullmatch(re_str, 'abcm\t/'))
print(fullmatch(re_str, 'abc G/'))

1
2
3
4
5
3) \d  - 匹配任意一个数字字符
re_str = r'a\d\dc'
print(fullmatch(re_str, 'a78c'))
print(fullmatch(re_str, 'a00c'))

1
2
3
4
5
6
7
8
9
4) \s   -   匹配任意一个空白字符
空白字符:空格、回车(\n)、制表符(\t)

re_str = r'a\sb'
print(fullmatch(re_str, 'a b'))
print(fullmatch(re_str, 'a\nb'))
print(fullmatch(re_str, 'a\tb'))
print(fullmatch(re_str, 'a b')) # None

1
* 5) \w  -  匹配任意一个字母、数字或者下划线  (不好用)
1
2
3
4
5
6
7
8
6
\D - 匹配任意一个非数字字符
\S - 匹配任意一个非空白字符

print(fullmatch(r'a\Sb\D', 'a>b='))
print(fullmatch(r'a\Sb\D', 'a b=')) # None
print(fullmatch(r'a\Sb\D', 'a>b0')) # None

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
7) [字符集]    -   匹配字符集中任意一个字符
注意:一个[]只能匹配一个字符
[多个普通字符] - 例如:[abc],可以匹配a或者b或者c
[包含\开头的特殊符号的字符集] - 例如:[\dabc],可以匹配任意数据或者a或者b或者c

[包含减号在两个字符之间的字符集] - 这个时候的减号表示谁到谁(注意:减号前面的字符的编码必须小于减号后面的)
例如:
[a-z] - 匹配任意一个小写字母
[a-d] - 匹配a、b、c、d中的任意一个字符
[A-Z] - 匹配任意一个大写字母
[1-9] - 匹配19中任意一个数字字符
[\u4e00-\u9fa5] - 匹配任意一个中文字符
[a-zA-Z]、[A-Za-z] - 匹配任意一个字母
[a-z123] - 匹配任意一个小写字母,或者1或者2或者3
[a-z\d] - 匹配任意一个小写字母或者任意一个数字


re_str = r'a[xym]b'
print(fullmatch(re_str, 'axb'))
print(fullmatch(re_str, 'ayb'))
print(fullmatch(re_str, 'amb'))
print(fullmatch(re_str, 'azb')) # None

re_str = r'a[16]b'
print(fullmatch(re_str, 'a1b'))
print(fullmatch(re_str, 'a6b'))

re_str = r'a[a\db]b'
print(fullmatch(re_str, 'a1b'))
print(fullmatch(re_str, 'aab'))
print(fullmatch(re_str, 'abb'))

print(fullmatch(r'x[a-z]y', 'xmy'))

print(fullmatch(r'x[a-zA-Z]y', 'xmy'))
print(fullmatch(r'x[a-zA-Z]y', 'xKy'))

print(fullmatch(r'x[a-zA-Z*&]y', 'x*y'))
print(fullmatch(r'x[a-zA-Z*&]y', 'xMy'))

print(fullmatch(r'x[0-9]y', 'x5y'))

print(fullmatch(r'x[-09]y', 'x-y'))
print(fullmatch(r'x[-09]y', 'x0y'))
print(fullmatch(r'x[-09]y', 'x9y'))

1
2
3
4
5
6
7
8
9
8) [^字符集]   -   匹配任意一个不在字符集任意一个字符
[^abc] - 匹配除了a、b、c以外的任意一个字符
[^a-z] - 匹配除了小写字母以外的任意一个字符

print(fullmatch(r'a[^\u4e00-\u9fa5]c', 'a是c')) # None
print(fullmatch(r'a[^a-zA-Z]c', 'aKc')) # None
print(fullmatch(r'a[a-z^]c', 'a^c'))


注意:[]中的-和^只有放在指定位置的时候才有特殊功能,否则在[]中就是一个普通的符号。

3.检测类符号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from re import fullmatch, findall

检测类符号的存在不影响被匹配的字符串长度,它的作用是在匹配成功的前提下检测符号所在的位置是否符号要求。
检测类符号的用法:先去掉检测类符号,看是否能匹配成功,如果失败整个正则匹配失败。如果成功再来看检测类符号所在的位置是否符合要求。

1. \b - 检测是否是单词边界
单词边界 - 能够区分出两个不同单词的符号都属于单词边界,例如:空白、标点符号、字符串开头、字符串结尾

re_str = r'abc\b123'
print(fullmatch(re_str, 'abc123')) # None
print(fullmatch(re_str, 'abc 123')) # None

re_str = r'abc,\b123'
print(fullmatch(re_str, 'abc,123'))

print(fullmatch(r'abc\s\b123', 'abc 123'))


# findall(正则表达式, 字符串) - 获取字符串中所有满足正则表达式的子串


str1 = '12ksksj78ss 34抗生素,89 试7试看90 56 江苏省23'
result1 = findall(r'\d\d', str1)
print(result1)

result2 = findall(r'\d\d\b', str1)
print(result2)

result3 = findall(r'\b\d\d\b', str1)
print(result3)

1
2
3
4
5
2. \B   -   检测是否是非单词边界

result3 = findall(r'\d\d\B', str1)
print(result3)

1
2
3
4
5
3. ^  -  检测是否是字符串开头

re_str = r'^\d\d'
print(fullmatch(re_str, '12'))
print(findall(r'^\d\d', str1))
1
2
3
4
5
4. $  -  检测是否是字符串结尾

re_str = r'\d\d$'
print(fullmatch(re_str, '67'))

4.匹配次数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from re import fullmatch, match, findall
import requests

1. * - 匹配0次或者多次(任意次数)
用法:匹配类符号*
a* - 匹配任意多个a
\d* - 匹配任意多个数字字符

print(fullmatch(r'a*b', 'b'))
print(fullmatch(r'a*b', 'aab'))
print(fullmatch(r'a*b', 'aaaaaaab'))
print(fullmatch(r'\d*b', '245899b'))
print(fullmatch(r'[abc]*x', 'aabccax'))

1
2
3
4
5
6
2. +    -   匹配1次或多次(至少一次)

print(fullmatch(r'a+b', 'b')) # None
print(fullmatch(r'a+b', 'ab'))
print(fullmatch(r'a+b', 'aaaaab'))

1
2
3
4
5
6
7
8
3. ?    -   匹配0次或1

re_str = r'[-+]?[1-9]\d'
print(fullmatch(re_str, '-12'))
print(fullmatch(r'a?b', 'b'))
print(fullmatch(r'a?b', 'ab'))
print(fullmatch(r'a?b', 'aab')) # None

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
4. {}
{N} - 匹配N次
{M,N} - 匹配M到N次
{,N} - 匹配最多N次
{M,} - 匹配至少M次
* == {0,}
+ == {1,}
? == {0,1}

print(fullmatch(r'\d{4}', '5670'))

print(fullmatch(r'\d{3,5}', '234'))
print(fullmatch(r'\d{3,5}', '2334'))
print(fullmatch(r'\d{3,5}', '23342'))
print(fullmatch(r'\d{3,5}', '233429')) # None
print(fullmatch(r'\d{3,5}', '23')) # None

print(fullmatch(r'\d{,5}', '23'))
print(fullmatch(r'\d{,5}', ''))
print(fullmatch(r'\d{,5}', '899080')) # None

print(fullmatch(r'\d{3,}', '23')) # None
print(fullmatch(r'\d{3,}', '23234234233'))

# 注意:匹配次数对应的符号的前面必须是匹配类符号
'''print(fullmatch(r'+{2,3}', '++')) # re.error '''

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
5. 贪婪和非贪婪
在匹配次数不确定的时候,匹配模式分为贪婪和非贪婪两种,默认是贪婪模式。
在匹配成功的前提下,贪婪是匹配次数选最多的那个次数;非贪婪是匹配次数最少的那个次数。

*、+、?、{M,N}、{M,}、{,N} - 贪婪的
*?、+?、??、{M,N}?、{M,}?、{,N}? - 非贪婪的

print(match(r'\d{3}', '234hj监管机构'))
print(match(r'a.*b', 'asmmdb监管机构')) # asmmdb
print(match(r'a.*?b', 'asmmdb监管机构')) # asmmdb

# 'asb'、'asbmmb'、'asbmmbdb' 有三种情况可以成功,因为贪婪所以最后匹配次数最多的情况
print(match(r'a.*b', 'asbmmbdb监管机构')) # asbmmbdb
print(match(r'a.*?b', 'asbmmbdb监管机构')) # asb

# 实例
response = requests.get('http://api.tianapi.com/auto/index?key=c9d408fefd8ed4081a9079d0d6165d43&num=10')
result = findall(r'"title":"(.+?)"', response.text)
print(result)


5.分组和分支

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from re import fullmatch
1. () - 分组
作用1:将()中的内容作为一个整体,进行整体相关操作,例如,整体控制次数
作用2:通过 '\M' 重复前面第M个分组匹配到的结果, M从1开始
作用3:捕获(在findall中讲)

str1 = '78nm34ms10xp'
print(fullmatch(r'\d\d[a-z]{2}\d\d[a-z]{2}\d\d[a-z]{2}', str1))
print(fullmatch(r'(\d\d[a-z]{2}){3}', str1))

str1 = r'abababab'
print(fullmatch(r'(ab)+', str1))


print(fullmatch(r'(\d{2})abc\1', '89abc89'))
print(fullmatch(r'(\d{2})abc\1', '89abc34')) # None

'''print(fullmatch(r'\d{2}abc\1', '89abc89')) # re.error'''

print(fullmatch(r'(\d{3})([a-z]{3})-\2', '234ams-ams'))
print(fullmatch(r'(\d{3})([a-z]{3})-\1', '234ams-234'))
print(fullmatch(r'(\d{3})([a-z]{3})-\2\1', '234ams-ams234'))
print(fullmatch(r'(\d{3})([a-z]{3})-\1{2}', '234ams-234234'))

''' print(fullmatch(r'(\d{3})-\2([a-z]{3})', '234ams-ams')) # re.error '''


1
2
3
4
5
6
7
2. |    -   分支
正则1|正则2 - 先用正则1进行匹配,如果成就直接匹配成功,如果匹配失败再用正则2进行匹配

# 要求能同时匹配'abc98' 和 'abcMKP'
print(fullmatch(r'abc\d{2}|abc[A-Z]{3}', 'abcKMP'))
print(fullmatch(r'abc(\d{2}|[A-Z]{3})', 'abcMKP'))

1
2
3
4
5
6
7
8
9
10
11
3. 转义符号
在特殊符号前加\,让符号的功能消失,变成一个普通符号

print(fullmatch(r'\+\d{3}', '+234'))
print(fullmatch(r'\[\d{3}\]', '[234]'))
print(fullmatch(r'\\dabc', '\dabc'))

# 如果是独立存在有特殊功能的符号,将符号放入[]中其功能也会自动消失
print(fullmatch(r'[+*?|()^$.]abc', '$abc'))
print(fullmatch(r'[\^abc\-z\]]123', ']123'))

6.模块

1
2
3
4
5
6
7
8
9
10
11
import re
compile(正则表达式) - 编译正则表达式,返回一个正则表达式对象

fullmatch(正则表达式, 字符串)
正则表达式对象.fullmatch(字符串)

re_obj = re.compile(r'\d{3}')
print(re_obj.fullmatch('234'))

print(re.fullmatch(r'\d{3}', '234'))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2. 
fullmatch(正则表达式, 字符串) - 让正则表达式和整个字符串进行匹配(完全匹配),匹配失败返回None,匹配成功返回匹配对象
match(正则表达式, 字符串) - 匹配字符串开头(判断字符串的开头是否符合正则的规则),匹配失败返回None,匹配成功返回匹配对象

result = re.fullmatch(r'(\d{3})-([A-Z]+)', '345-K')
print(result) # <re.Match object; span=(0, 3), match='345'> - 匹配对象

1) 获取匹配到的字符串
匹配对象.group() / 匹配对象.group(0) - 获取整个正则匹配到的结果
匹配对象.group(N) - 获取第N个分组匹配到的结果

print(result.group()) # 345-K
print(result.group(1)) # 345
print(result.group(2)) # K

1
2
3
4
5
6
7
8
9
10
11
12
13
3. search(正则表达式, 字符串)   -   获取字符串中第一个满足正则表达式的子串。返回结果是None或者匹配对象

result = re.search(r'\d{3}', '试试看234ksjs,345')
print(result) # <re.Match object; span=(3, 6), match='234'>
print(result.group()) # 234


2) 获取匹配结果在原字符串中的位置信息
匹配对象.span() - 返回的是一个元组,元组中的元素是开始下标和结束下标,结束下标对应的位置取不到
匹配对象.span(N)

print(result.span())

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
4.
findall(正则表达式, 字符串) - 获取字符串中所有满足正则的子串,返回的是列表,列表中的元素是子串(没有分组的时候)
如果正则中只有一个分组:返回的列表中的元素是每个分组匹配到的结果
如果正则中有两个或两个以上的分组: 返回的列表中的元素是元组,元组中的元素是每个分组匹配到的结果

result = re.findall(r'\d{2}', '34ssd908计算机上23,udh89,试试89123')
print(result) # ['34', '90', '23', '89', '89', '12']

result = re.findall(r'(\d{2})\D', '34ssd908计算机上23,udh89,试试89123')
print(result) # ['34', '08', '23', '89']

result = re.findall(r'((\d[a-z]){2})', '2m4m司机师傅9k0o试试3k5l--')
print(result) # [('2m4m', '4m'), ('9k0o', '0o'), ('3k5l', '5l')]

result = re.findall(r'(\d{2})-([a-z]{3})', '23-msn数据是98-kop圣诞节发货')
print(result) # [('23', 'msn'), ('98', 'kop')]


1
2
3
4
5
6
7
8
5.finditer(正则表达式, 字符串)  -   获取字符串中所有满足正则的子串,返回的是一个迭代器,迭代器是匹配对象

result = re.finditer(r'(\d{2})-([a-z]{3})', '23-msn数据是98-kop圣诞节发货')
print(result)
r1 = next(result)
print(r1, r1.group(), r1.group(1), r1.group(2))


1
2
3
4
5
6
7
6. split(正则表达式, 字符串)    -   将字符串中所有满足正则表达式的子串作为切割点,对字符串进行切割
re.split(正则表达式, 字符串, N) - 将字符串中前N个满足正则表达式的子串作为切割点,对字符串进行切割

result = re.split(r'\d+', '是是9564s双生视界09世纪东方和3d失敬失敬2试试')
print(result)


1
2
3
4
5
6
7
8
7. 
sub(正则表达式, 字符串1, 字符串2) - 将字符串2中所有满足正则表达式的子串替换成字符串1
sub(正则表达式, 字符串1, 字符串2, N) - 将字符串2中前N个满足正则表达式的子串替换成字符串1

result = re.sub(r'\d+', '*', '是是9564s双生视界09世纪东方和3d失敬失敬2试试')
print(result)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
8. flags参数
上面的每一个函数都一个参数flags,用来设置正则参数
1) 单行匹配和多行匹配参数:re.S、re.M(默认的)
单行匹配:.可以匹配\n
多行匹配:.不能和\n匹配

flags=re.S <==> r'(?s)正则表达式'

2) 忽略大小写:re.I
flags=re.I <==> r'(?i)正则表达式'

flags=re.S|re.I <==> r'(?si)正则表达式'

print(re.fullmatch(r'a.b', 'a\nb', flags=re.M)) # None
print(re.fullmatch(r'a.b', 'a\nb')) # None
print(re.fullmatch(r'a.b', 'a\nb', flags=re.S))
print(re.fullmatch(r'(?s)a.b', 'a\nb'))

print('---------------------------------------------------')
print(re.fullmatch(r'abc', 'abc'))
print(re.fullmatch(r'abc', 'Abc')) # None
print(re.fullmatch(r'abc', 'ABc', flags=re.I))
print(re.fullmatch(r'(?i)abc', 'ABc'))

print(re.fullmatch(r'a.b', 'A\nb', flags=re.S|re.I))
print(re.fullmatch(r'(?is)a.b', 'A\nb'))

json和异常

1.json

1.1 json是一种通用的数据格式

1.2 json是一种什么样的数据格式(通用)

1
2
3
4
5
6
7
8
一个json有且只有一个数据,唯一的这个数据必须是json支持的类型的数据
json支持的类型:
数字 - 包含所有的整数和小数,表示的时候直接写 例如:900,-23
字符串 - 只能用双引号("abc")支持转义字符
布尔 - true和false两个值
空值 - null
数组 - 相当于python中的列表:[元素1,元素2] (元素必须是json数据类型)
字典 - 相当于python中的字典,但是键只能是字符串,例如:{"name":"小明""age":18}

1.3 python数据和json数据之间的相互转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
python 提供一个json模块,这个模块中有两个函数专门用来支持json和python的相互转换
json --> python
数字 int/float
字符串 str,可能双引号会变成单引号
布尔值 bool,true->True,false->False
空值 null->None
数组 list
字典 dict

loads(json格式的字符串) - 将json格式的字符串转换成对应的python数据
json格式的字符串:字符串内容是一个合法的json数据(去掉字符串外面的引号,剩下的部分是一个合法的json数据)

python -> json
int/float 数字
str 字符串,单引号会变成双引号
bool True->true,False->false
list/tuple 数组
dict 字典;键会转换成字符串
None null

dumps(python数据) - 将python数据转换为对应的json格式的字符串
100 -> '100'
True -> 'true'

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
### json转换为python
import json
result = json.loads('"abc"')
print(result)

result = json.loads('["abc",123,true,null]')
print(result)

### python转换为json

result = json.dumps([100,'abc',True,None])
print(result,type(result))
result1 = json.loads(result)
print(result1)

# import json
# result = json.dumps([])
# print(result,type(result))
# result1 = json.loads(result)
# print(result1,type(result1))

2.异常

1
2
程序报错就叫程序异常
如果程序出现异常会终止程序的执行

2.1 捕获异常

1
异常捕获就是让程序中指定的代码段在出现异常后不终止程序的执行,让程序接着执行

2.2 如何捕获异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
结构一:捕获任意异常
try:
需要抛出异常的代码
except:
捕获到异常后会执行的代码

结构二:捕获指定类型异常
try:
需要抛出异常的代码
except 异常类型:
捕获到异常后会执行的代码

结构三:同时捕获多种异常
try:
需要抛出异常的代码
except (异常类型1,异常类型2):
捕获到异常后会执行的代码

结构四:同时捕获多种异常
try:
需要抛出异常的代码
except 异常类型1:
处理方法1
except 异常类型2:
处理方法2
.....

结构五:可以在前面几种结构后面加finally 后接代码段
finally后面的代码段都会执行(不管是否出现异常或者异常是否被捕获)

2.3抛出异常 - 主动抛出异常

1
raise 异常类型

实现简单的登录注册功能

1.常用系统模块

1.1 os模块

1
import os

1.1.1 os.getcwd() - 获取当前工作目录

1.1.2 os.listdir(文件夹路径) - 获取指定文件夹所有文件名称

1.1.3 os.path.abspath(文件夹路径) - 返回指定文件的绝对路径

1.2 time模块

1
import time

1.2.1 time.time() - 获取当前时间

1
print(time.time())  ## 1627611752.606797 以时间戳显示

时间戳 - 用指定时间到1970年1月1日0时0分0秒(格林威治时间)的时间差来表示时间的方式(秒)

格林威治时间和北京时间有8小时时差 - 现在格林威治时间比北京时间晚8小时

1.2.2 time.localtime() - 获取当前时间的本地时间

1.2.3 time.localtime(时间戳) - 将时间戳对应的时间转换成本地时间

1
2
print(time.localtime())
print(time.localtime(1627611752.606797))

1.2.3 time.sleep(时间) - 程序休眠指定时间(秒)

1.2.4 time.strftime(时间格式,结构体时间) - 结构体时间转字符串时间

1
2
3
4
5
6
7
8
9
10
11
12
13
XXXX年XX月XX日 xx:xx:xx
%Y - 年
%m - 月
%d - 日
%H - 时(24小时制)
%I - 时(12小时制)
%M - 分
%S - 秒
%p - AM、PM(上午、下午)
%a - 星期英文单词缩写
%A - 星期英文单词全拼
%b - 月份英文缩写
%B - 月份英文全拼
1
2
3
4
5
6
7
8
9
t1 = time.localtime()
result = time.strftime('%Y年%m月%d日 %H:%M:%S', t1)
print(result) # 2021年07月30日 10:54:35

result = time.strftime('%Y-%m-%d %H:%M:%S', t1)
print(result)

result = time.strftime('%m月%d日 %p%I:%M %B', t1)
print(result)

1.2.5将字符串时间转换成结构体时间

time.strptime(字符串时间,时间格式)

1
2
3
t3 = time.strptime('2010-10-2', '%Y-%m-%d')
print(f'周{t3.tm_wday + 1}')
print(t3)

1.2.6将字符串时间转换成时间戳(先将字符串时间转换成结构体时间)

time.mktime(结构体时间) - 将结构体时间转换成时间戳

1
2
result = time.mktime(t3)
print(result)

1.3datetime类型 - 处理包含年月日时分秒的时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# 1)创建datatime时间对象
import datetime
from datetime import datetime, timedelta

# datetime(year, month, day, hour=0, minute=0, second=0)
t1 = datetime(2010, 10, 2)
print(t1) # 2010-10-02 00:00:00

t2 = datetime(2011, 9, 4, 11, 13, 40)
print(t2) # 2011-09-04 11:13:40

# 2)获取时间属性
# 时间对象.year、时间对象.moth、...
print(t2.month) # 9
print(t2.hour) # 11

# 3)获取当前时间
t3 = datetime.now()
print(t3)

# 4)将datetime转换成结构体时间
t4 = t3.timetuple()
print(t4)

# 5)将datetime转换成字符串时间
st5 = t3.strftime('%Y年%m月%d日 %a')
print(st5)

# 6)将字符串时间转换成datetime
str6 = '2003-7-1'
t5 = datetime.strptime(str6, '%Y-%m-%d')

# 2.timedelta - 主要用于时间的加减操作
t6 = t5 + timedelta(days=45)
print(t6) # 2003-08-15 00:00:00

t7 = t5 - timedelta(days=8)
print(t7) # 2003-06-23 00:00:00

t8 = t5 + timedelta(days=1, hours=5, minutes=15)
print(t8) # 2003-07-02 05:15:00

1.4 hashlib模块 - 用于生成数据的hash摘要

1
2
3
4
5
hash 加密算法主要有:md5 和 shaxxx
1. hash加密的特点
a.不可逆(通过原数据加密后无法还原)
b.相同的数据通过相同的算法产生的摘要(密文)是一样的
c.不同大小的数据在使用相同的算法产生的摘要的长度一致

1.4.1使用hashlib产生数据的摘要

1
2
3
4
5
6
7
8
9
10
11
12
13
import hashlib
## 1.根据算法创建hash对象 - hashlib.算法名()
hash1 = hashlib.md5()

## 2.添加数据
## hash对象.update(二进制数据)

pw = '123456'
hash1.update(pw.encode())

## 3.获取摘要
result = hash1.hexdigest()
print(result)

python二进制数据类型 - bytes

1
2
3
4
5
6
7
8
9
字符串和bytes的相互转换
1)str -> bytes
方法1bytes(字符串,'utf-8')
方法2b'字符集'
方法3:字符串.encode()

2)bytes -> str
方法1str(二进制数据,'utf-8')
方法2:二进制数据.decode()
1
2
3
4
5
6
7
8
9
10
print(bytes('abc','utf-8'))

b1 = b'abc'
print(type(b1))

str1 = 'abc'
print(str1.encode())

print(str(b1,'utf-8'))
print(b1.decode())

2.文件操作

2.1数据的存储

1
2
3
4
程序中保存的数据默认都是存储在运行内存中,运行内存中的数据在程序结束之后会被释放
保存数据需要将数据存储到磁盘中
将数据存储到磁盘的过程又叫数据本地化
数据本地化的基本原理 - 将数据通过文件存储到磁盘中

2.2操作文件内容

1
2
3
文件操作主要解决两个问题:
a.怎么将程序中的数据通过文件存储到磁盘中
b.怎么在程序中使用保存在文件中的数据

2.2.1 文件操作的基本步骤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
第一步:打开文件
open(文件路径,读写模式,编码方式encoding=文件编码方式)
1.文件路径 - 文件在计算机中的位置信息,以字符串的方式提供值(绝对路径,相对路径)
绝对路径 - 文件在计算机中的全路径
相对路径 - ./(当前目录) 当前项目所在目录
2.读写模式 - 设置打开文件之后是读操作还是写操作,设置操作数据的类型是字符串还是二进制
"""
r - 只读 w - 只写(覆盖原有文件) a - 只写(对数据追加)
t - 按字符串数据类型操作(t可以省略) b - 按二进制数据类型操作
"""
3.encoding - 文件编码方式 以b的方式打开文件的时候encoding不赋值
注意:二进制文件只能以b的方式打开
第二步:文件操作
文件对象.read() - 从读写位置开始到文件结尾(默认为文件开头)
文件对象.readline() - 从读写位置开始读到一行的结尾(只有文本文件有效)
文件对象.readlines() - 以列表形式返回一个对象,每个元素是一行数据
文件对象.write(数据) -
第三步:文件关闭
文件对象.close()
1
2
3
4
f = open(r'E:\\qianfeng1.txt','r+',encoding='utf-8')
print(f.read())

f.seek(0) - 设置读写位置到文件开头

数据持久化的基本步骤:

1
2
3
4
5
第一步:确定需要持久化的数据(确定哪个数据在下一次程序运行的时候还要用)
第二步:创建文件保存数据初始值
第三步:在程序中需要这个数据的时候从文件中读数据
第四步:如果数据发生改变,要将最新的数据写回文件中

练习1:打印程序运行次数

1
2
3
4
5
6
7
f = open(r'E:\shujuchijiu\aa.txt','r',encoding='utf-8')
count = int(f.read())
count+=1
print(count)
f = open(r'E:\shujuchijiu\aa.txt','w',encoding='utf-8')
f.write(str(count))
f.close()

练习2:添加学生,并且在添加完成后显示所有学生信息(只需要学生名字)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
请输入学生姓名: 小明
小明 ['小明']

请输入学生姓名:小花
小明 小花 ['小明', '小花']

请输入学生姓名:q
(程序结束)

请输入学生姓名: 张三
小明 小花 张三 ['小明', '小花', '张三']

请输入学生姓名: 李四
小明 小花 张三 李四 ['小明', '小花', '张三', '李四']

请输入学生姓名:q
(程序结束)
1
2
3
4
5
6
7
8
9
10
11
12
while True:
name = input("请输入学生姓名:")
if name == 'q':
exit()
else:
f = open(r'E:\shujuchijiu\bb.txt', 'r', encoding='utf-8')
all_student = eval(f.read())
all_student.append(name)
print(all_student)
f = open(r'E:\shujuchijiu\bb.txt', 'w', encoding='utf-8')
f.write(str(all_student))
f.close()

作业

控制台登陆注册操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
def login_info():
print('='*50)
print(' '*2 ,'** ','欢迎来到X管理系统',' **')
print()
print()
print(" " * 10, '1.登陆')
print(" " * 10, '2.注册')
print(" " * 10, '3.退出')
print("=" * 50)
xuanze()

def xuanze():
a = int(input("请选择1-3:"))
if a == 1:
login1()
elif a == 2:
zhuce1()
elif a == 3:
f1.close()
f2.close()
print("结束退出")
exit()
else:
print("输入有误将返回")
login_info()

f1 = open(r'E:\shujuchijiu\zhanghao.txt', 'r', encoding='utf-8')
all_zhanghao = eval(f1.read())
f2 = open(r'E:\shujuchijiu\mima.txt', 'r', encoding='utf-8')
all_mima = eval(f2.read())


def zhuce1():
global all_zhanghao
global all_mima
zhanghao = input("请输入账号(3-6位):")
if not 3 <= len(zhanghao) <=6:
print("用户名格式错误")
zhuce1()
mima = input("请输入密码(6-12位)")
if not 6 <= len(mima) <=12:
print("密码格式错误")
zhuce1()
if zhanghao in all_zhanghao:
print("注册失败,该账号已经注册过!")
login_info()
else:
all_zhanghao.append(zhanghao)
all_mima.append(mima)
f1 = open(r'E:\shujuchijiu\zhanghao.txt', 'w', encoding='utf-8')
f1.write(str(all_zhanghao))
f2 = open(r'E:\shujuchijiu\mima.txt', 'w', encoding='utf-8')
f2.write(str(all_mima))
print("注册成功")
login_info()


def login1():
global all_zhanghao
global all_mima
zhanghao = input("请输入账号:")
mima = input("请输入密码:")
if zhanghao not in all_zhanghao:
print("该账号未注册")
login_info()
elif mima not in all_mima:
print("登陆失败,密码错误")
login_info()
else:
if mima != all_mima[all_zhanghao.index(zhanghao)]:
print("登陆失败,密码错误")
login_info()
else:
print("登陆成功")
login_info()

login_info()