Python笔记汇总

132 阅读30分钟

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 一个平台标识符,如sunos5win32

  • 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.strftimedatetime对象格式化成字符串
  • datetime.strptime 将字符串按照一定的格式转换成datetime对象
  • time 表示一个时间类
  • datetime.now 系统的当前时间
  • day Datetime对象的属性,类似的还有minutehour
  • days Timedelta的属性,类似的还有minuteshours

DateTime模块转换参数表

参数含义
%A星期的名称,如 Monday
%B月份名,如 January
%m用数字表示月份(01~12)
%d用数字表示月份中的一天(01~31)
%Y四位的年份,如2015
%y两位的年份,如15
%H24小时制的小时数(00~23)
%I12小时制的小时数(01~12)
%pam或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__ or next() 得到迭代器中下一项的值

  • __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匹配文本字符串的字面值 literalfoo
re1re2匹配正则表达式 re1 re2foobar
.匹配任何字符(除了\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(oou)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'>
     """
    

groupgroups分组使用

  • 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('&amp', '&'))
             #   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
     ------------------------
     """