1、列表与元组的区别
却别对比
列表 | 元组 |
---|---|
内容允许扩展 | 内容不可改变 |
内存存储动态变化 | 创建后固定不变 |
效率较低 | 效率较高 |
运行时数据需要变更时使用 | 用于芭比村稳定不变的数据 |
(适用于)保存天气数据、故事数据 | (适用于)保存国家名、元素周期表 |
2、系列类型的互相转换
list()
- 将其他序列类型转换为列表
tuple()
- 将其他序列类型转换为元组
join()、str()
- 将其他序列类型转换为字符串
str()
函数用于将单个数据转换为字符串join()
对列表进行连接
3、集合set()
集合的数学运算
交集intersection()
``` python
# 交集,获取两个集合中重复的部分
info = { 'name', 'age', 'sex' }
info1 = { 'class', 'high' }
info3 = info.intersection(info1)
print(info3)
# 对原有的集合进行更新
info.intersection_update(info1)
print(info)
```
并集union()
```python
# 并集,将两个集合所有的元素合并、去重
info = { 'name', 'age', 'sex' }
info1 = { 'name', 'class', 'high' }
info3 = info.union(info1)
print(info3)
# 并集没有更新函数
```
差集difference()
# 差集,是指两个集合之间的差异部分
info = { 'name', 'age', 'sex' }
info1 = { 'name', 'class', 'high' }
info3 = info.difference(info1)
print(info3)
# 获取双向差集,symmetric(均衡)
info4 = info.symmetric_difference(info1)
print(info4)
info.difference_update(info1)
print(info)
判断子级issubset()
# 判断集合的子级
info1 = {4, 5, 6, 7}
info2 = {1, 2, 3, 4, 5, 6, 7, 8}
print(info1.issubset(info2))
判断父级issuperset()
```python
# 判断集合的父级
info1 = {4, 5, 6, 7}
info2 = {1, 2, 3, 4, 5, 6, 7, 8}
print(info2.issuperset(info1))
```
判断重复isdisjoint()
```python
# isdisjoint() 函数判断两个集合是否存在重复元素
# 结果为 True 时表示不存在重复,结果为 False 时表示存在重复
info1 = {4, 5, 6, 7}
info2 = {1, 2, 3, 4, 5, 6, 7, 8}
print(info1.isdisjoint(info2))
```
4、生成式
列表生成式
# 生成式语法:[被追加的数据 循环语句 循环或者判断语句] | {}
list = [i * 10 for i in range(10, 20) if i % 2 == 0]
list1 = [i * j for i in range(1, 5) for j in range(1, 5)]
'''
for i in range(1, 5):
for j in range(1, 5):
list1.append(i * j)
'''
字典生成式
list = ['Tom', 'Lock', 'Join']
dict = {i + 1 : list[i] for i in range(0, len(list))}
'''
for i in range(0, len(list)):
dict[i + 1] = list[i]
'''
集合生成式
info = { i * j for i in range(1, 4) for j in range(1, 4) if i == j }
'''
for i in range(1, 4):
for j in range(1, 4):
if i == j:
info.add(i * j)
'''
5、函数
-
print()
向控制台打印 -
input()
接受控制台输入 -
format()
格式化字符串 -
list()
创建列表 -
lower()
字符串转小写 -
upper()
字符串转大写 -
find()
在原有的字符串中查找是否包含某一个字符或者子字符串- 包含返回索引位置
- 不包含返回-1
6、模块与包
dir
列出对象所有的属性及方法help
查看类,方法的帮助信息__name__
模块名称__file__
文件全路径
模块导入及定位
-
导入
import os
-
定位:
当前包-->内置函数-->sys.path(环境变量)
OS模块
-
environ
包含环境变量的映射import os env = os.environ print(env)
-
system(command)
在子shell
中执行操作系统命令import os # 传入系统命令打开系统计算器 os.system('calc')
-
sep
路径中使用的分隔符 -
pathsep
分隔不同路径的分隔符 -
linesep
行分隔符('\n'、'\r'或'\r\n') -
urandom(n)
返回n个字节的强加密随机数据 -
argv
命令行参数,包括脚本名 -
getcwd
放回当前所在目录 -
modules
一个字典,将模块名映射到加载的模块 -
path
一个列表,包含要在其中查找模块的目录的名称 -
pathform
一个平台标识符,如sunos5
或win32
-
mkdir/rmdir
创建和删除文件夹 -
os.path
文件目录相关操作-
os.path.isdir(e)
判断当前文件是否为文件夹import os os.path.isdir('文件名称') # 返回值为 Ture / False
-
os.path.isfile(e)
判断当前文件是否为文件 -
os.path.exists(e)
判断目录/文件是否存在 -
os.path.basename(e)
获取文件名称 -
os.path.join()
-
os.path.makedirs(文件名称)
-
DateTime模块
-
import datetime now_time = datetime.datetime.now() print('now: {0}'.format(now_time)) # 获取当前日期 print('now day: {0}'.format(now_time.date())) # 获取当前时间 print('now time: {0}'.format(now_time.time())) print('now day1: {0}'.format(datetime.datetime.today())) print('year: {0}'.format(now_time.year))
timedelta
对日期/时间进行加减操作时使用date
date类表示一个日期datetime.strftime
将datetime
对象格式化成字符串datetime.strptime
将字符串按照一定的格式转换成datetime
对象time
表示一个时间类datetime.now
系统的当前时间day
Datetime
对象的属性,类似的还有minute
,hour
等days
Timedelta
的属性,类似的还有minutes
,hours
等
DateTime模块转换参数表
参数 | 含义 |
---|---|
%A | 星期的名称,如 Monday |
%B | 月份名,如 January |
%m | 用数字表示月份(01~12) |
%d | 用数字表示月份中的一天(01~31) |
%Y | 四位的年份,如2015 |
%y | 两位的年份,如15 |
%H | 24小时制的小时数(00~23) |
%I | 12小时制的小时数(01~12) |
%p | am或pm |
%M | 分钟数 (00~59) |
%S | 秒数(00~61) |
-
Demo
from datetime import datetime, date, time, timedelta print('now {0}'.format(datetime.now())) # 时间/日期字符串格式化转换 time = '2018-10-31 13:42:59' formatp_date = datetime.strptime(time, '%Y-%m-%d %H:%M:%S') print(formatp_date) now_time = datetime.now() formatf_time = now_time.strftime('%Y-%m-%d %H:%M:%S') print(formatf_time) # datetime之间的加减操作 next_time = now_time + timedelta(days = 5, hours = 42, minutes = 4, seconds = 56, microseconds = 444) print(next_time)
第三方模块
-
Django
一个自带电池的web开发框架pip install Django # or 下载安装包,进行解压然后执行 python setup.py install python install Django.zip # 卸载 pip uninstall Django
-
Flask
简单易用,快速上手的微型web开发框架 -
mysqlclient
使用python
操作mysql
数据的工具库
7、包
包简介
-
可以用来组织模块(可以包含其他 模块的模块)
-
目录必须包含文件
_init_.py
├── publish/ └── package_a/ ├── _init_.py/ ├── module_a.py/ ├── module_b.py/ └── package_b/ ├── _init_.py/ ├── module_a.py/ ├── module_b.py/
包的引用
-
引入整个包
import module
-
只是引入所需要的属性和方法
from module.xx.xx import module
-
指定别名
from module.xx.xx import xx as renename
-
引入所有
from module.xx import *
8、python虚拟环境搭建
虚拟环境virtualenv
安装
pip install virtualenv
# 新建环境目录
mkdir envs
# 构建虚拟环境中的flask
virtualenv flask
#
cd flask/Scripts
# 进入虚拟环境
activate
# 安装flask
pip install flask
# 测试是否安装成功
python -> import flask -> quit()
# 退出虚拟环境
deactivate.bat
virtualenvwrapper-win
-
-
用来管理virtualenv的扩展包,方便env虚拟环境管理
$ pip install virtualenvwrapper ... $ export WORKON_HOME=~/Envs $ mkdir -p $WORKON_HOME $ source /usr/local/bin/virtualenvwrapper.sh $ mkvirtualenv env1
-
-
安装
# -win仅针对与Windows系统使用,如果是Linux或其他系统,可直接使用 virtualenvwrapper pip install virtualenvwrapper-win
-
Demo
# 设置环境变量 WROKON_HOME c:\envs(目录地址)
IDEA设置虚拟环境
-
File >>> Settings >>> Project: chapter01 >>> Project interpreter # next add >>> Virtualenv Environment
pipenv
-
安装
pip install pipenv
-
创建及使用虚拟环境
mkdir py2.6 cd py2.6 # 创建(需要本地安装相对应版本的python) pipenv --python 2.6 # 安装库 pipenv install requests # 进入虚拟环境 pipenv shell # 退出 exit
-
注意
由于版本更新,python最低 支持Python2.7,请直接下载2.7版本进行操作
9、自定义工具包
Demo
# trans/tools.py
from datetime import datetime
import random
def gen_trans_id(date=None):
"""
根据传入的时间得到一个唯一的交易流水ID
:param date: 日期
:return: 交易流水ID
"""
# 如果没有传入时间,则使用系统当前时间
if date is None:
date = datetime.now()
# 保证字符串唯一
# 日期+时间+毫秒+随机数(6位数随机数)
return '{0}{1}'.format(date.strftime('%y%m%d%H%M%S%f'), random.randint(100000, 999999))
# return date.strftime('%y%m%d%H%M%S%f') + str(random.randint(100000, 999999))
# work/tools.py
import os.path
import constants
def get_file_type(file_name):
"""
根据文件的名称来判断文件的类型
:param file_name: 文件名称
:return: 文件的类型
-1: 位置文件类型
0: 图片类型的文件
1: world文档
2: excel文档
3: ppt文档
"""
# 默认文件为未知类型
result = constants.FILE_TYPE_UNKNOWN
# 判断传入的参数是否是文件名称
if not os.path.isfile(file_name):
return result
# 将文件的后缀名统一转换为小写
path_name, ext = os.path.splitext(file_name)
ext = ext.lower()
if ext in ('.png', '.jpg', '.gif', '.tmp'):
return constants.FILE_TYPE_IMG
elif ext in ('.doc', 'docx'):
return constants.FILE_TYPE_DOC
elif ext in ('.xls', 'xlsx'):
return constants.FILE_TYPE_EXCEL
elif ext in ('.ppt', 'pptx'):
return constants.FILE_TYPE_PPT
return result
# constants.py
"""
常量文件
"""
FILE_TYPE_UNKNOWN = 10 # 未知文件类型
FILE_TYPE_IMG = 11 # 图片类型
FILE_TYPE_DOC = 12 # world文档
FILE_TYPE_EXCEL = 13 # excel类型
FILE_TYPE_PPT = 14 # ppt文档
# test_module.py
from trans.tools import gen_trans_id
from work import tools as work_tools
from datetime import datetime
def test_trans_tool():
""" 测试trans包下的tools模块 """
order_id1 = gen_trans_id()
print(order_id1)
date = datetime(2015, 10, 2, 12, 30, 45)
order_id2 = gen_trans_id(date)
print(order_id2)
def text_work_tool():
""" 测试work包下的tools模块 """
file_name = 'C:\Users\qinyh\Desktop\WeChat Image_20210709085348.jpg'
rest = work_tools.get_file_type(file_name)
print(rest)
if __name__ == '__main__':
test_trans_tool()
text_work_tool()
# 目录
├── utils/
└── trans/
├── _init_.py/
├── tools.py/
└── work/
├── _init_.py/
├── tools.py/
├── constants.py/
├── test_module.py/
10、常用高阶函数
lambda
函数
- lambda函数是一种表达式,创建内嵌的简单匿名函数
filter
函数
-
过滤器(返回一个列表,其中包含对其执行函数时结果为真的所有元素)
-
filter(function, list)
def condition(value): return value % 2 != 0 def use_filter(list): rest = filter(condition, list) # rest = filter(lambda n: n % 2 != 0, list) return rest if __name__ == '__main__': arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] rest = use_filter(arr) print(list(rest))
map
函数
-
创建一个列表,其中包含对指定序列包含的项执行指定函数返回的值
-
map(function, sequence, ...)
def sum_num(value): """求给定数的立方""" return value * value * value def test_use_map(list): """ 使用map函数计算给定列表的每一项的立方值 :param list: list/type int 类型的列表或者元组 :return: 原来列表中每一项的立方 """ return map(sum_num, list) def test_use_lambda(list): """ 使用lambda函数计算给定列表的每一项的立方值 :param list: list/type int 类型的列表或者元组 :return: 原来列表中每一项的立方 """ return map(lambda n: n * n * n, list) if __name__ == '__main__': arr = [1, 2, 3, 4, 5, 6, 7, 8] rest = test_use_map(arr) print(list(rest)) print("======================") rest_lambda = test_use_lambda(arr) print(list(rest_lambda))
sum
函数
-
求和函数
def use_sum_num(list): return sum(list) if __name__ == '__main__': arr = [1, 2, 3, 4, 5, 6 ,7] rest = use_sum_num(arr) print(rest)
reduce
函数
-
使用指定的函数将序列的前两个元素合二为一,再将结果与第三个元素合二为一,依此类推,直到处理完整个序列并得到一个结果
from functools import reduce def use_reduce_sum(x, y): return x + y def test_use_reduce(list): return reduce(use_reduce_sum, list) return reduce(lambda x, y: x + y, list) if __name__ == '__main__': arr = [1, 2, 3, 4, 5, 6, 7, 8] rest = test_use_reduce(arr) print(rest)
11、文件读写
文件读写模式
-
参数表
值 描述 r
(read)读取模式(默认值) w
(write)写入模式 x
独占写入模式 a
附加模式 b
二进制模式(与其他模式结合使用) t
文本模式(默认值,与其他模式结合使用) +
读写模式(与其他模式结合使用)
open()
函数打开文件
-
file 文件路径
-
mode 打开模式
-
encoding 指定打开编码
file = open('file.txt')
close()
函数关闭文件
file.close()
width
- 到达该语句末尾时,将自动关闭文件,即便出现异常亦是如此
with open('somefile.txt') as file:do_something(file)
文件读取
read()
-
读取文件,可以指定参数,表示读几个字符(字节)
def test_read_file(): # 读取文件 # file_name = 'C:\Users\qinyh\Desktop\learp\read_file\file.txt' file_name = 'C:/Users/qinyh/Desktop/learp/read_file/file.txt' # 使用普通方式打开文件 file = open(file_name, encoding = 'utf-8') # 读取文件内容 # file_read = file.read() # 读取指定的内容 file_read = file.read(8) # 随机读取 file.seek(20) file_read = file.read() print(file_read) # 关闭文件 file.close() if __name__ == '__main__': test_read_file()
readline()
-
读取一行数据,可以指定参数,表示读取前几个字符(字节)
def test_read_file(): # 读取文件 # file_name = 'C:\Users\qinyh\Desktop\learp\read_file\file.txt' file_name = 'C:/Users/qinyh/Desktop/learp/read_file/file.txt' # 使用普通方式打开文件 file = open(file_name, encoding = 'utf-8') # 读取文件内容 file_read = file.readline() print(file_read) # 关闭文件 file.close() if __name__ == '__main__': test_read_file()
readlines()
-
读取所有行,并返回列表
def test_read_file(): # 读取文件 # file_name = 'C:\Users\qinyh\Desktop\learp\read_file\file.txt' file_name = 'C:/Users/qinyh/Desktop/learp/read_file/file.txt' # 使用普通方式打开文件 file = open(file_name, encoding = 'utf-8') # 读取文件内容 file_read = file.readlines() print(file_read) print(len(file_read)) for value in file_read: print(value) if __name__ == '__main__': test_read_file()
with
-
Demo
def test_read_file(): # 读取文件 # file_name = 'C:\Users\qinyh\Desktop\learp\read_file\file.txt' file_name = 'C:/Users/qinyh/Desktop/learp/read_file/file.txt' # 使用普通方式打开文件 with open(file_name, encoding = 'utf-8') as file: # 读取文件内容 file_read = file.readlines() print(file_read) print(len(file_read)) for value in file_read: print(value) if __name__ == '__main__': test_read_file()
文件写入
write()
-
Demo
def write_file(): file_name = 'writefile.txt' # 以写入的方式打开文件 file = open(file_name, 'w') # 写入一行内容 file.write('hello') # 写入换行 file.write('\n') # 再写入一行内容 file.write('world') # 关闭文件 file.close() if __name__ == '__main__': write_file()
writelines()
-
写入多行内容
def writelines_file(): file_name = 'writelinesfile.txt' with open(file_name, 'w', encoding='utf-8') as file: arr = ['第一行', '\n', '第二行'] file.writelines(arr) if __name__ == '__main__': writelines_file()
使用write生成日志
-
Demo
def create_logs(): """ 记录用户的日志 """ rest = '用户: {0} - 访问时间 {1}'.format(random.randint(1000, 9999), datetime.now()) + '\n' file_name = 'user_logs.txt' print(rest) with open(file_name, 'a', encoding = 'utf-8') as file: file.write(rest) if __name__ == '__main__': create_logs()
读写操作
-
Demo
def read_and_write(): file_name = 'read_and_write.txt' with open(file_name, 'r+', encoding = 'utf-8') as file: read_rest = file.read() # 如果有1,写入一行aaa # 如果没有,就写一行数据bbb if '1' in read_rest: file.write('bbb') else: file.write('aaa') file.write('\n') if __name__ == '__main__': read_and_write()
文件备份
-
Demo
import os import os.path class FileBackUp(object): """ 文件备份 """ def __init__(self, src, dist): """ 构造方法 :param src: 目录 需要备份的文件目录 :param dist: 目录 备份后的目录 """ self.src = src self.dist = dist def read_files(self): """ 读取src目录下的所有文件 """ file_list = os.listdir(self.src) print(file_list) for val in file_list: # 循环处理每一个文件/文件夹 self.backup_file_new(val) def backup_file(self, file_name): """ 处理备份 :param file_name: 文件/文件夹的名称 """ pass # 1、判断dist目录是否存在,如果不存在,则创建这个目录 if not os.path.exists(self.dist): os.makedirs(self.dist) print('指定的目录不存在,创建完成') # 2、判断文件是否为要保存的文件 # 拼接完整路径 file_src_path = os.path.join(self.src, file_name) file_dist_path = os.path.join(self.dist, file_name) # 首先判断是否为文件夹,然后借助于文件的后缀名进行判断 if os.path.isfile(file_src_path) and os.path.splitext(file_src_path)[-1].lower() == '.txt': print(file_src_path) # 3、读取文件内容 with open(file_dist_path, 'w', encoding='utf-8') as file_dist: print('>> 开始备份【{0}】'.format(file_name)) with open(file_src_path, 'r', encoding='utf-8') as file_src: while True: rest = file_src.read(100) if not rest: break # 4、把读取到的内容写入到新的文件中 file_dist.write(rest) # 释放垃圾(多余的未读取完成的) file_dist.flush() print('>>> 【{0}】备份完成'.format(file_name)) else: print('文件类型不符合备份要求,跳过>>') # 备份文件优化版 def backup_file_new(self, file_name): """ 处理备份 :param file_name: 文件/文件夹的名称 """ pass # 1、判断dist目录是否存在,如果不存在,则创建这个目录 if not os.path.exists(self.dist): os.makedirs(self.dist) print('指定的目录不存在,创建完成') # 2、判断文件是否为要保存的文件 # 拼接完整路径 file_src_path = os.path.join(self.src, file_name) file_dist_path = os.path.join(self.dist, file_name) # 首先判断是否为文件夹,然后借助于文件的后缀名进行判断 if os.path.isfile(file_src_path) and os.path.splitext(file_src_path)[-1].lower() == '.txt': # 3、读取文件内容 with open(file_dist_path, 'w', encoding='utf-8') as file_dist,\ open(file_src_path, 'r', encoding='utf-8') as file_src: print('>> 开始备份【{0}】'.format(file_name)) while True: rest = file_src.read(100) if not rest: break # 4、把读取到的内容写入到新的文件中 file_dist.write(rest) # 释放垃圾(多余的未读取完成的) file_dist.flush() print('>>> 【{0}】备份完成'.format(file_name)) else: print('文件类型不符合备份要求,跳过>>') if __name__ == '__main__': # # 要备份的文件目录地址 # src_path = 'C:\Users\yima1\Desktop\py_learn\chapter04\src' # # 备份后的目录地址 # dist_path = 'C:\Users\yima1\Desktop\py_learn\chapter04\dist' # 当前代码的目录名称 # C:\Users\yima1\Desktop\py_learn\chapter04\ test_backup.py base_path = os.path.dirname(os.path.abspath(__file__)) # 要备份的文件目录地址 src_path = os.path.join(base_path, 'src') print(src_path) # 备份后的目录地址 dist_path = os.path.join(base_path, 'dist') print(dist_path) bak = FileBackUp(src_path, dist_path) bak.read_files()
12、类的特性
类
- 类是墨子,确定对象将会拥有的特征(属性)和行为(方法)
- 对象是类的实力表现
- 类是对象的类型
- 对象是特定类型的数据
类和对象的关系
- 类:抽象的概念;模板
- 对象:一个看得到、摸得着的具体实例
graph TD
类 --> 实例化 --> 对象
封装
- 将类的某些信息隐藏在类的内部,不允许外部程序直接访问
- 通过该类提供的方法来实现对隐藏信息的操作和访问
- 隐藏对象的信息
- 留出访问的接口
特点
- 只能通过规定的方法访问数据
- 隐藏类的实例细节,方便修改和实现
继承
多态
-
同一个方法,在不同的类中,最终呈现不同的结果
-
必要条件:
- 满足继承关系
- 需要方法的重写
-
Demo
"""猫科动物细节化""" class BaseCat(object): """ 猫科动物的基础类 """ tag = '猫科动物' def __init__(self, name): print('BaseCat init') self.name = name def eat(self): print('猫都要吃东西') class Tiger(BaseCat): """ 老虎类,也是猫科动物 """ def __init__(self, name, color): super().__init__(name) self.color = color print('Tiger init') def eat(self): super().eat() print('老虎还喜欢吃猪肉') # 多态,定义自定义方法 def show_info(self): """ 展示信息 """ print('Tiger: {0}, 颜色:{1}'.format(self.name, self.color)) class Panda(BaseCat): """熊猫""" pass if __name__ == '__main__': tiger = Tiger('华南虎', 'yellow') tiger.show_info() print("=============")
类的属性和方法
-
self
表示类的实例 -
__doc__
文档信息""" 猫科动物类 """
-
__module__
模块信息 -
tag
自定义类属性 -
catch
自定义类方法 -
Demo
class Cat(object): """ 猫科动物类 """ # 类的属性 tag = '猫科动物' def __init__(self, name, age): # 实例化后的属性 self.name = name self.__age = age pass def catch(self): print('猫可以捕捉老鼠') def eat(self): """ 吃 :return: """ print('猫喜欢吃鱼') def get_age(self): print('{0}年龄是{1}岁'.format(self.name, self.__age)) def Tiger(Cat): pass
类的实现
-
class Cat(object): tag = '田园猫' """ 猫科动物类 """ def __init__(self, name, age): self.name = name self.__age = name def set_age(self, age): """ 改变动物年龄 """ self.__age = age def show_info(self): """ 是否展示信息 """ rest = '我叫{0},今年{1}岁'.format(self.name, self.__age) print(rest) return rest def eat(self): """ 动物吃 """ print('喜欢吃鱼') def catch(self): """ 动物行为 """ print('喜欢捕捉老鼠')
类的实例
-
Demo
class Cat(object): tag = '田园猫' """ 猫科动物类 """ def __init__(self, name, age, sex='男孩'): self.name = name # 两个_开头表示为私有变量 self.__age = age self.sex = sex def set_age(self, age): """ 改变动物年龄 """ self.__age = age def show_info(self): """ 是否展示信息 """ rest = '我叫{0},今年{1}岁,我的性别是{2}'.format(self.name, self.__age, self.sex) print(rest) return rest def eat(self): """ 动物吃 """ print('喜欢吃鱼') def catch(self): """ 动物行为 """ print('喜欢捕捉老鼠') class Tiger(object): pass if __name__ == '__main__': # 实例化动物 cat_black = Cat('小黑', 2) cat_black.show_info() print(cat_black.name) print(cat_black.__age)
-
isinstance()
判断是否为类的实例# 类的实例判断 print(isinstance(cat_black, Cat)) print(isinstance(cat_black, Tiger))
类的继承
-
issubclass()
判断是否为其子类 -
super(Cat, self).eat
调用父类的方法 -
Demo
"""猫科动物细节化""" class BaseCat(object): """ 猫科动物的基础类 """ tag = '猫科动物' def __init__(self, name): self.name = name def eat(self): print('猫都要吃东西') class Tiger(BaseCat): """ 老虎类,也是猫科动物 """ def eat(self): super(Tiger, self).eat() print('老虎还喜欢吃猪肉') class Panda(BaseCat): """熊猫""" pass class PetCat(BaseCat): """家猫""" def eat(self): super(PetCat, self).eat() print('还喜欢吃猫粮') class HuaCat(PetCat): """中华田园猫""" def eat(self): super(HuaCat, self).eat() print('还喜欢吃零食') class DuanCat(PetCat): """英国短毛猫""" def eat(self): super(DuanCat, self).eat() # print('啥都喜欢吃') if __name__ == '__main__': # 实例化中华田园猫 cat = HuaCat('小黄') cat.eat() print('===============') # 实例化英国短毛猫 cat_duan = DuanCat('Red') cat_duan.eat() # 子类的判断 print(issubclass(DuanCat, BaseCat)) # True print(issubclass(DuanCat, PetCat)) # True print(issubclass(DuanCat, Tiger)) # False print(issubclass(DuanCat, Panda)) # False
类的多重继承
-
注意:
使用多重继承时,如果调用的方法时重名的,调到一个方法后,则不再执行后面的方法
-
Demo
"""猫科动物细节化""" class BaseCat(object): """ 猫科动物的基础类 """ tag = '猫科动物' def __init__(self, name): self.name = name def eat(self): print('猫都要吃东西') class ProtectedMixin(object): """受省级保护的类""" def protected(self): print('是受省级重点保护的') class CountryProtectedMixin(object): """受国家保护的类""" def protected(self): print('是受国家级重点保护的') class Tiger(BaseCat, ProtectedMixin, CountryProtectedMixin): """ 老虎类,也是猫科动物 """ def eat(self): super(Tiger, self).eat() print('老虎还喜欢吃猪肉') class Panda(BaseCat, ProtectedMixin): """熊猫""" pass if __name__ == '__main__': # 实例化 panda = Panda('卧龙熊猫') panda.eat() panda.protected() tiger = Tiger('华南虎') tiger.protected() print("=============") # 验证子类信息 print(issubclass(Panda, ProtectedMixin)) # True print(issubclass(Panda, BaseCat)) # True
类的高级特性
@property
-
将类的方法当作属性来使用
-
Demo
class PetCat(object): def __init__(self, name, age): self.name = name # 设置私有属性,不能被修改 self.__age = age @property def age(self): return self.__age @age.setter def age(self, value): # 判断是否为整数类型 if not isinstance(value, int): print('年龄只能是整数') return 0 if value < 0 or value > 100: print('年龄只能介于0-100之间') return 0 self.__age = value # 描述符 @property def show_info(self): return '我叫:{0},今年{1}岁'.format(self.name, self.age) def __str__(self): # return self.show_info() return '我叫:{0}'.format(self.name) if __name__ == '__main__': cat_black = PetCat('小黑', 20) # rest = cat_black.show_info() print(cat_black) # 使用@property后 print(cat_black.show_info) cat_black.age = 5 print(cat_black.show_info)
__slots__
-
为指定的类设置一个静态属性列表(为属性很少的类节约内存空间)
-
使用
__slots__
后不允许给实例添加新的属性 -
使用
__slots__
后不允许给实例添加新的方法(函数) -
Demo
class PetCat(object): # 使用__slots__限制字段,使用__slots__后不允许给实例添加新的属性 __slots__ = ('name', 'age') def __init__(self, name, age): self.name = name self.age = age # 设置私有属性,不能被修改 # self.__age = age # 描述符 @property def show_info(self): return '我叫:{0},今年{1}岁'.format(self.name, self.age) def __str__(self): # return self.show_info() return '我叫:{0}'.format(self.name) class HuaCat(PetCat): __slots__ = ('color', ) if __name__ == '__main__': # cat_black = PetCat('小黑', 20) # rest = cat_black.show_info # print(rest) # # 给实例添加新的属性 # cat_black.color = '白色' # print(cat_black.color) cat_white = HuaCat('小黑', 20) rest = cat_white.show_info print(rest) # 给实例添加新的属性 cat_white.color = '白色' print(cat_white.color)
类的静态方法和实例方法
@staticmethod
- 静态方法
@classmethod
-
类的方法
-
cls
表示当前Class类 -
self
表示当前实例 -
用于设计模式
-
Demo
class Cat(object): tag = "猫科动物" def __init__(self, name): self.name = name @staticmethod def breath(): """ 呼吸 """ print("猫需要呼吸") @classmethod def show_info(cls): """ 显示猫的信息 """ print('类的属性:{0},实例属性:{1}'.format(cls.tag, cls.name)) @classmethod def show_info2(cls, name): """ 显示猫的信息 """ return cls(name) def show_info3(self): """ 显示猫的信息 """ print('类的属性:{0},实例属性:{1}'.format(self.tag, self.name)) if __name__ == '__main__': # Cat.breath() # cat = Cat() # cat.breath() # # cat.show_info() cat = Cat.show_info2('小黄') cat.show_info3()
13、面向对象应用
Python内置类属性
__init__ ( self [,args...] )
构造函数,简单的调用方法: obj = className(args)__str__
用于将值转化为适于人阅读的形式,简单的调用方法 : str(obj)__dict__
类的属性(包含一个字典,由类的数据属性组成)__doc__
类的文档字符串__name__
类名__module__
类定义所在的模块(类的全名是'main.className',如果类位于一个导入模块mymod中,那么className.module 等于 mymod)__bases__
类的所有父类构成元素(包含了一个由所有父类组成的元组)__del__
对象销毁的时候被调用,析构方法, 删除一个对象,简单的调用方法 : del obj__repr__( self )
转化为供解释器读取的形式,简单的调用方法 : repr(obj)__cmp__ ( self, x )
对象比较,简单的调用方法 : cmp(obj, x)
装饰器
-
用于拓展原来函数功能的一种函数
-
返回函数的函数
-
在不用更改原函数的代码前提下给函数增加新的功能
-
Demo
def log(func): """ 记录函数执行的日志 """ def warpper(): print('开始执行') func() print('执行完毕') print('================') # 返回函数的函数 return warpper @log def hello(): print('Hello World') @log def test(): print('Test ...') if __name__ == '__main__': hello() test()
有参装饰器
-
魔法参数
*args, **kwargs
-
Demo
def log(name=None): """ 记录函数执行的日志 """ def decorator(func): """ 使用魔法参数 """ def warpper(*args, **kwargs): print('{0}开始执行'.format(name)) print(args) print(kwargs) rest = func(*args, **kwargs) print('{0}执行完毕'.format(name)) print('================') return rest # 返回函数的函数 return warpper return decorator # @log() or @log('you') def hello(): print('Hello World') @log('sum') def sum (x, y, *args, **kwargs): return x + y if __name__ == '__main__': hello() rest = sum(5, 6) print(rest)
有参装饰器@wraps
-
Demo
from functools import wraps def log(name=None): """ 记录函数执行的日志 """ def decorator(func): """ 使用魔法参数 """ @wraps(func) def wrapper(*args, **kwargs): print('{0}开始执行'.format(name)) print('--wrapper--doc: {0}'.format(func.__doc__)) print('--wrapper--name: {0}'.format(func.__name__)) rest = func(*args, **kwargs) print('{0}执行完毕'.format(name)) print('================') return rest # 使用@wraps等同于以下赋值 # wrapper.__doc__ = func.__doc__ # wrapper.__name__ = func.__name__ # 返回函数的函数 return wrapper return decorator # @log() or @log('you') def hello(): """ wraps简单功能模拟 """ print('Hello World') if __name__ == '__main__': print('doc: {0}'.format(hello.__doc__)) print('name: {0}'.format(hello.__name__)) hello()
类的装饰器
-
Demo
def eat(cls): """ 吃东西装饰器 """ cls.eat = lambda self: print('{0}>要吃东西'.format(self.name)) return cls @eat class Cat(object): """ 猫类 """ # 定义构造函数 def __init__(self, name): self.name = name if __name__ == '__main__': cat = Cat('小黑') cat.eat()
迭代器
-
iter()
创建迭代器序列 -
__next__
ornext()
得到迭代器中下一项的值 -
__iter__
定义迭代器 -
Demo
class PowNumber(object): """ 迭代器 """ value = 0 def __next__(self): self.value += 1 # 设置当数值大于10时,停止迭代 if self.value > 10: raise StopIteration return self.value * self.value """ 定义迭代器 """ def __iter__(self): return self if __name__ == '__main__': pow = PowNumber() print(pow.__next__()) print(next(pow)) print(pow.__next__()) # 遍历迭代器 for key in pow: print(key)
生成器
-
是一种使用普通函数语法定义的迭代器
-
包含
yield
语句的函数都被成为生成器 -
不使用
return
返回一个值,而是可以生成 多个值,每次一个 -
每次使用
yield
生成一个值后,函数都将会冻结,即在此停止执行 -
被重新唤醒后,函数将从停止的地方开始继续执行
-
Demo
def pow(): yield 1 yield 2 yield 3 yield 4 def pow_number(): return (x * x for x in [1, 2, 3, 4, 5]) def pow_array(): for x in range(1, 6): yield x * x if __name__ == '__main__': item = pow() print(next(item)) print(next(item)) rest = pow_number() print(rest.__next__()) print(rest.__next__()) arr = pow_array() print(arr.__next__()) print(arr.__next__())
range函数
-
Demo
def use_range(): for key in range(5, 10): print(key) class IterRange(object): def __init__(self, start, end): self.start = start - 1 self.end = end def __next__(self): self.start += 1 if self.start >= self.end: raise StopIteration return self.start def __iter__(self): return self class GenRange(object): """ 使用生成器模拟range函数 """ def __init__(self, start, end): self.start = start - 1 self.end = end def get_num(self): while True: if self.start >= self.end - 1: break self.start += 1 yield self.start def get_num(start, end): start -= 1 while True: if start >= end - 1: break start += 1 yield start if __name__ == '__main__': # use_range() rest = IterRange(5, 10) print(next(rest)) print('---------------------') gen = GenRange(5, 10).get_num() arr = list(gen) print(arr) print('---------------------') gen_fun = get_num(5, 10) print(list(gen_fun))
异常捕获
-
内置异常类
类名 描述 Exception 几乎所有的异常类都是从它派生而来的 AttributeError 引用属性或给它赋值失败时引发 OSError 操作系统不能执行指定的任务(如打开文件)时引发的,有多个子类 IndexError 使用序列中不存在的索引时引发,为LookupError的子类 KeyError 使用映射中不存在的键时引发,为LookupError的子类 NameError 找不到名称(变量)时引发 SyntaxError 代码不正确时引发 TypeError 将内置操作或函数用于类型不正确的对象时引发 ValueError 将内置操作或函数用于这样的对象时引发,其类型正确但包含的值不合适 ZeroDivisionError 在除法或求模运算的第二个参数为零时引发 -
try...except
捕获所有异常(或指定的异常) -
try...except...finally
finally处理必不可少的逻辑 -
Demo
def sum(one, two): return one / two def read_file(): try: file = open('text.txt', 'r') read = file.read() print(read) except: print('error') finally: # 防止文件不存在而报错 try: file.close() print('close') except: pass if __name__ == '__main__': try: rest = sum(5, 'file') print(rest) except Exception as error: print(error) except (ZeroDivisionError, TypeError) as error: print(error) except ZeroDivisionError: print('错误信息,0不能作为除数') except TypeError: print('错误信息,请输入数字') print('-----------------------') read_file()
自定义异常
-
Demo
# 自定义异常类 class ApiException(Exception): """ 我的自定义异常 """ err_code = '' err_msg = '' def __init__(self, err_code=None, err_msg=None): self.err_code = self.err_code if self.err_code else err_code self.err_msg = self.err_msg if self.err_msg else err_msg def __str__(self): return 'Error: {0}, {1}'.format(self.err_code, self.err_msg) # 参数不合法自定义异常函数 class InvalidCtrlExec(ApiException): """ 当参数不合法时触发 """ err_code = '4000' err_msg = '不合法的调用凭证' # 参数不正确自定义异常函数 class BadPramsException(ApiException): """ 校验参数类型不合法 """ err_code = '4002' err_msg = '输入的参数必须为整数' def sum(num1, num2): """ 除法的实现 """ # 两个数必须为整数 if not isinstance(num1, int) or not isinstance(num2, int): raise BadPramsException() # 除数不能为0 if num2 == 0: raise ApiException('4000', '除数不能为0') return num1 / num2 if __name__ == '__main__': try: rest = sum(5, 's') print(rest) # 因为 BadPramsException 是 ApiException 的子类,所以在捕获异常时,要以小到大捕获 except BadPramsException as err: print('出错了') print('=======================') print(err) except ApiException as err: print('出错了') print(err)
异常的抛出/传递
- 如果在异常产生的地方不捕获,那么它将会一层一层的往上传递
- 异常产生以后就会逐层的向外抛,直到捕获以后才会停止抛出
14、内存管理
赋值语句内存分析
垃圾回收机制
内存管理机制
15、正则表达式
正则表达式中的符号
符号 | 描述 | 示例 | |||
---|---|---|---|---|---|
literal | 匹配文本字符串的字面值 literal | foo | |||
re1 | re2 | 匹配正则表达式 re1 或 re2 | foo | bar | |
. | 匹配任何字符(除了\n 以外) | b.b | |||
匹配字符串起始部分 | ^Dear | ||||
$ | 匹配字符串终止部分 | /bin/*sh$ | |||
* | 匹配0次或 多次前面出现的正则表达式 | [A-Za-z0-9]* | |||
+ | 匹配1次或多次前面出现的正则表达式 | [a-z]+\ .com | |||
? | 匹配0次或1次前面出现的正则表达式 | goo? | |||
{N} | 匹配N次前面出现的正则表达式 | [0-9]{3} | |||
{M, N} | 匹配 M~N次前面出现的正则表达式 | [0-9]{5, 9} | |||
[…] | 匹配来自字符集的任意单一字符 | [aeiou] | |||
[..x-y..] | 匹配x~y范围中的任意单一字符 | [0-9],[A-Za-z] | |||
[^…] | 不匹配此字符集中出现的任何一个字符,包括某一范围的字符(如果在次字符集中出现) | [^aeiou],A-Za-z0-9 | |||
(* | + | ? | {})? | 用于匹配上面频繁出现 / 重复出现符号的非贪婪版本(*、+、?、{}) | .*?[a-z] |
(…) | 匹配封闭的正则表达式,然后另存为子组 | ([0-9]{3})?,f(oo | u)bar |
特殊字符
特殊字符 | 描述 | 示例 |
---|---|---|
\d | 匹配任何十进制数字,与[0-9]一致(\D 与 \d 相反,不匹配任何非数值型的数字) | data\d+.txt |
\w | 匹配任何字母数字字符,与[A-Za-z0-9_] 相同(\S与之相反) | [A-Za-z_]\w+ |
\s | 匹配任何空格字符,与[\n\t\r\v\f] 相同(\S与之相反) | of/sthe |
\b | 匹配任何单词边界(\B与之相反) | \bThe\b |
\N | 匹配已保存的子组 | price:\16 |
\c | 逐字匹配任何特殊字符 c(即,仅按照字面意义匹配,不匹配特殊含义) | ., , * |
\A(\Z) | 匹配字符串的起始(结束) | \ADear |
使用
*
匹配0次或多次
a*bc
aabcd => aabc
cbc => bc
+
匹配一次或多次
a+bc
aabcd => aabc
cbc =>
?
匹配0次或1次
a?bc
aabcd => abc
cbc => bc
{N}
匹配指定的N次
a{3}
aaaabc => aaa
{M, N}匹配M-N次,最大化优先
a{2, 5}
aabcd => aa
caaaacd => aaaa
caaaaaaaaacd => aaaaa
同类型匹配
\d
匹配数字
\d
c123d => 1
\w
匹配数字和字母
\w{3}
he666 => he6
\s
匹配任何空格字符
a\s{2}a
cccca accc => a a
^
匹配以**开头
^he.
hello world => hel
shello world =>
$
匹配以**结尾
.ld$
hello world => rld
hello world! =>
匹配特殊字符
``进行字符转义
.com
imooc.com => .com
^^http://w+
http://w+
[]
指定要匹配的集合
[abc]{2}
cba666 => cb
[a-zA-Z]{2}
[^]
指定不要匹配的内容
# 匹配只要不是abc中任意一个值,匹配长度为2
[^abc]{2}
正则表达式分组
- 在出现重复字符串时使用分组
- 使用
()
进行分组,使用(?<word>\w+)
指定组名,则word
就是组名 - 从左向右,以分组的左括号为标志,第一个出现的分组的组号为
1
,第二个为2
,以此类推
()
正则分组
(abc){2}
abcabcabc => abcabc
(\d{1, 3}.){3}\d{1, 3}
192.168.100.1
\1、\2
反向引用
He (l..e)s her \1r
He loves her lover
He likes her liker
# 设置分组
He (?<name>l..e)s her \k<name>r
贪婪模式
贪婪匹配(默认匹配)
- 在整个表达式匹配成功的前提下,尽可能多的匹配
ab.+c
abacaxcd => abacaxc
非贪婪匹配
- 在整个表达式匹配成功的前提下,以最少的的匹配字符
- 只需要在匹配
pattern
中加上?
即可
ab.*?c
ab.+?c
abacaxcd => abac
身份证正则匹配
-
Demo
// 正则匹配身份证号码 /* 430656 1996 10 01 5493 430656 1996 10 01 548X */ /* * 需要用到分组的概念: * 1. 前6位:区域编号 * 2. 接下来的4位:出生年份 * 3. 接下来的4位:出生日期 * 4. 最后4位 * 5. 倒数第二位:性别 * */ // 最简身份证匹配正则 let regex = '\d{17}(0-9|X)' // 优化,细化年份匹配 regex = '(\d{6})(\d{4})((\d{2})(\d{2}))\d{2}\d{1}([0-9]|X)'
电子邮箱正则匹配
-
Demo
// 电子邮箱表达式 /* * 123@qq.com * 123@vip.qq.com * 123@foxmail.com * 123@163.com * */ /* * 邮箱规则分析: * 1. 必须有一个@符 * 2. @不能在开头,也不能在结尾 * 3. .是一定存在的 * 4. .不能再开头,也不能在结尾 * 5. 邮箱前半部分只能是英文字母(大小写)、数字、下划线、中划线,英文半角 * 6. @后面的部分一定有.,并且.不能挨在一起,也不能挨着@ * */ let mail_regex = [a-zA-z0-9_-]+@[a-zA-Z0-9-]+(.[a-zA-X0-9-]+)*(.[a-zA-X0-9]{2,5})
正则进阶
re
模块
re模块
匹配选项
属性 | 描述 |
---|---|
re.l、re.IGNORECASE | 不区分大小写的匹配 |
re.L、re.LOCALE | 根据所使用的本地语言环境通过\w、\W、\b、\B、\s、\S实现匹配 |
re.M、re.MULTILINE | ^和$分别匹配目标字符串中行的起始和结尾,而不是严格匹配整个字符串本身的起始和结尾 |
re.S、rer.DOTALL | "."(点号)通常匹配除了\n(换行符)之外的所有单个字符;该标记表示"."(点号)能匹配全部字符 |
re.X、re.VERBOSE | 通过反斜线转义,否则所有空格加上#(以及在该行中所有后续文字)都被忽略,除非在一个字符类中或者允许注释并且提高可读性 |
compile(regex, flags = 0)
- 使用任何可选的标记来编译正则表达式的模式,然后返回一个正则表达式对象
match(regex, string, flags = 0)
-
尝试使用带有可选的标记的正则表达式的模式来匹配字符串,如果匹配成功,就返回匹配对象;如果失败,就返回None
-
Demo
import re # 将正则表达式编译 regex = re.compile(r'hello', re.I) # 通过match进行匹配 rest = regex.match('Hello, world!') print(rest) print(dir(rest)) print('string', rest.string) print('re:', rest.re) print('groups:', rest.groups())
findall()
使用
-
findall(pattern, string[, flags])
-
查找字符串中所有(非重复)出现的正则表达式模式,并返回一个匹配列表
import re # 找出字符串中的数字 content = 'one1two12three333four44five5six698' num = re.compile(r'\d+') str = re.compile(r'[a-z]+', re.I) rest = num.findall(content) rest_str = str.findall(content) print('number:', rest) print('string:', rest_str) # 不编译 all_rest = re.findall(r'[a-z]+', content, re.I) all_num = re.findall(r'\d+', content, re.I) print(all_rest) print(all_num) """ print number: ['1', '12', '333', '44', '5', '698'] string: ['one', 'two', 'three', 'four', 'five', 'six'] ['one', 'two', 'three', 'four', 'five', 'six'] ['1', '12', '333', '44', '5', '698'] """
search()
使用
-
search(pattern, string, flags = 0)
-
使用可选标记搜索字符串中第一次出现的正则表达式模式,如果匹配成功,则返回匹配对象;如果失败,则返回None
import re content = 'hello, world' str = re.compile(r'world') # 使用search rest = str.search(content) print(rest) # 使用match rest_match = str.match(content) print(rest_match) # match vs search # match 在开头没找到时就停止查找 # search 在开头没找到时会继续查找 # 使用函数进行调用 rest_fun = re.search(r'world', content) print(rest_fun) """ print <re.Match object; span=(7, 12), match='world'> None <re.Match object; span=(7, 12), match='world'> """
group
与groups
分组使用
-
group(num)
返回整个匹配对象或编号为num的特定子组 -
groups()
返回一个包含所有匹配子组的元组(如果没有成功匹配,则返回一个空元组)import re def test_group(): content = 'hello, world' str = re.compile(r'world') rest = str.search(content) print(rest) if rest: # group的使用 print(rest.group()) # groups的使用 print(rest.groups()) # groupdict print(rest.groupdict()) def test_id_card(): """ 身份证号码正则匹配 """ card = re.compile('(\d{6})(\d{4})((\d{2})(\d{2}))\d{2}\d{1}([0-9]|X)') card = re.compile('(?P<number>\d{6})(?P<year>\d{4})((?P<month>\d{2})(?P<day>\d{2}))\d{2}\d{1}([0-9]|X)') # 两个身份证号码 card_id_one = '430656199610015493' card_id_two = '43065619961001549X' card_id = card.search(card_id_one) print(card_id.group()) # '(\d{6})' == 430656 print(card_id.group(1)) # 月,日 print(card_id.group(4)) print(card_id.group(5)) # Groups print(card_id.groups()) # Groupdict print(card_id.groupdict()) if __name__ == '__main__': test_group() test_id_card() """ print <re.Match object; span=(7, 12), match='world'> world () {} 430656199610015493 430656 10 01 ('430656', '1996', '1001', '10', '01', '3') {'number': '430656', 'year': '1996', 'month': '10', 'day': '01'} """
split()
正则分割
-
split(pattern, string, max=0)
-
根据正则表达式的模式分隔符,
split
函数将字符串分割为列表,然后返回成功匹配的列表,分隔最多操作max
次(默认分割所有匹配成功的位置) -
Demo
import re """ 使用split正则分割字符串 """ str = 'one1two12three333four44five5six698' plie = re.compile(r'\d+') rest = plie.split(str, 2) print(rest)
Sub()
正则替换
-
sub(pattern, repl, string, max=0)
-
使用
repl
替换string
中每一个匹配的子串后返回替换后的字符串,最多操作max
次(默认替换所有) -
Demo
import re """ 使用sub正则进行替换 """ str = 'one1two12three333four44five5six698' plie = re.compile(r'\d+') rest = plie.sub('@', str) print(rest) --> one@two@three@four@five@six@ """ 使用replace正则进行替换 """ rest_repla = str.replace('1', '@').replace('2', '@').replace('333', '@') print(rest_repla) --> one@two@@three@four44five5six698 """ 使用sub正则表达式替换位置 """ str_two = 'hello world' pile_two = re.compile(r'(\w+) (\w+)') rest_pos = pile_two.sub(r'\2 \1', str_two) print(rest_pos) --> world hello """ 使用sub正则表达式替换位置,并改变内容 """ def pos (value): return value.group(2).upper() + ' ' + value.group(1) rest_change = pile_two.sub(pos, str_two) print(rest_change) --> WORLD hello """ 使用匿名函数进行替换 """ rest_lamb = pile_two.sub(lambda value:value.group(2).upper() + ' ' + value.group(1), str_two) print(rest_lamb) --> WORLD hello
代码实现正则匹配图片地址
-
Demo
import re """ # 1、下载html # 2、设置正则规则 # 3、找到img标签 # 4、找到所在img标签的src属性 # 5、<img class="" style="" src="xxx" xx=""> # 6、<img.+src=".+".+> """ def replace_image (): """ 使用正则表达式找到图片的地址 """ # 1、读取html with open('img.html', encoding='utf-8') as file: html = file.read() print(html) # 2、设置正则规则,使用?规避非贪婪模式,使用分组获取到图片src地址 pile = re.compile(r'<img.+?src="(?P<src>.+?)".+?>', re.M | re.I) # 使用findall找到图片的列表 list_img = pile.findall(html) print(pile) print(len(list_img)) for value in list_img: print(value.replace('&', '&')) # TODO 使用urllib,requests将图片保存,涉及到爬虫 if __name__ == '__main__': replace_image()
-
Print控制台打印信息
""" <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div class="banner"> <img src="https://cdn.toodudu.com/uploads/2021/09/04/pc-banner-coupon.png" /> <img src="https://cdn.toodudu.com/20181221091337_82181.jpg" alt="" width="840" height="1179" title="" align="" /> <img src="https://cdn.toodudu.com/f5c0fea111dc81bf4ab8eed07956fc93.jpeg" alt="Titanium Dioxide A-120" style="" /> </div> </body> </html> ------------- re.compile('<img.+?src=\"(?P<src>.+?)\".+?>', re.IGNORECASE|re.MULTILINE) ----------------- 3 ------------------- https://cdn.toodudu.com/uploads/2021/09/04/pc-banner-coupon.png https://cdn.toodudu.com/20181221091337_82181.jpg https://cdn.toodudu.com/f5c0fea111dc81bf4ab8eed07956fc93.jpeg ------------------------ """