生成器
- 能够计算,2.返回值
生成器产生及元素方式
"""
产生生成器的方式:
1. 生成器推导式 : g1 = (x for x in range(5))
2. 在函数中使用 yield 关键字
"""
def test():
""" 迭代器 """
for i in range(3):
yield i
pass
if __name__ == '__main__':
g1 = (x for x in range(5))
print("g1:的类型", type(g1))
print(g1.__next__())
print(next(g1))
print(g1.send(None)) # 第一次 send 必须传入 None 值,后面的参数随便。此方式通常不常用
print(g1.send("suibian "))
print(g1.__next__())
# print(g1.__next__()) # 超过生成器范围报异常 StopIteration
"""
yield
"""
print("test:", type(test()))
list1 = list(x for x in test())
print("list1:", list1)
生成器产生元素方式
__next___
next()
- for 循环遍历
- send 方法,不常用
生成器与列表比较
类型 | 时间 | 内存 |
---|---|---|
生成器 | 时间长 | 开销大 |
列表 | 时间段 | 开销小 |
测试
import sys, time
"""
生成器与列表比较
1. 时间
2. 内存
"""
if __name__ == '__main__':
"""
存储 1- 10000 之间的偶数
"""
# list1 = []
# for i in range(2, 10000, 2):
# list1.append(i)
# print("list1",list1)
# """
# 列表推导式
# """
# list2 = [x for x in range(2, 10000, 2)]
# print("list2:", list2)
# list3 = [x for x in range(1, 10000) if x % 2 == 0]
# print("list3:", list3)
# list4 = [a + b for a in '123' for b in 'xyz']
# print("list4:", list4)
"""
使用列表推导式生成
"""
time.clock()
list5 = [x for x in range(2, 10000000, 2)]
end_time = time.clock() # 0.2045024
print("列表所花费的时间: {}".format(end_time))
print("列表内存开销:", sys.getsizeof(list5))
"""
使用生成器生成
"""
time.clock()
g1 = (x for x in range(2, 10000000, 2))
end_time2 = time.clock() - end_time # 3.2e-06
print("生成器所花费的时间:{}".format(end_time2))
print("生成器内存开销:", sys.getsizeof(g1))
# list6 = [x for x in g1]
# print("list6", list6)
迭代器
能够被 next() 访问, 并不断返回下一个值为新的对象
isinstance(对象 ,类型) 判断对象的类型,返回 True or False
可迭代性 | 迭代器 |
---|---|
集合类 list tuple dict | 生成器 |
生成器 generator |
"""
迭代器: 能够被 next() 内置函数访问,并返回下一个值为新的对象
可迭代性
1. 集合 list tuple dict
2. 生成器 generator
迭代器
生成器
"""
from collections import Iterable, Iterator
if __name__ == '__main__':
g1 = (_ for _ in range(5))
print(next(g1))
print("g1的类型为:", type(g1))
print("生成器是否具有可迭代性: ", isinstance(g1, Iterable))
print("生成器是否是迭代器", isinstance(g1, Iterator))
list1 = [x for x in range(5)]
if isinstance(list1, Iterable):
print("list 具有可迭代性.")
if isinstance(list1, Iterator):
print("list 是迭代器")
print(next(list1))
else:
print("list 不是迭代器")
else:
print("list 不具有可迭代性")
# tuple1 = (1, 2, 3)
tuple1 = tuple(list1)
if isinstance(tuple1, Iterable):
print("tuple 具有可迭代性.")
if isinstance(tuple1, Iterator):
print("tuple 是迭代器")
print(next(tuple1))
else:
print("tuple 不是迭代器")
else:
print("tuple 不具有可迭代性")
dict1 = dict(a=1, b=2)
if isinstance(dict1, Iterable):
print("dict 具有可迭代性.")
if isinstance(dict1, Iterator):
print("dict 是迭代器")
print(next(tuple1))
else:
print("dict 不是迭代器")
else:
print("dict 不具有可迭代性")
# 将可迭代对象转为迭代器
print("将可迭代对象转为迭代器")
list1 = iter(list1)
if isinstance(list1, Iterator):
print("list 是迭代器")
print(next(list1))
print([x for x in list1])
else:
print("list 不是迭代器")
闭包
"""
闭包: 一种特殊的函数
闭包创建的条件
1. 存在嵌套函数(外部函数和内部函数)
2. 内部函数需要使用外部函数的参数
3. 外部函数需要返回内部函数
闭包的使用
"""
def outer_func(num1):
""" 使用闭包方式, 计算两数之和"""
def inner_func(num2):
# 声明外部变量
nonlocal num1
num1 += 1
return num1 + num2
# 返回内部函数
return inner_func
result = outer_func(10)
print(result(10))
print(result(20))
闭包与函数
"""
使用闭包求两个二维坐标之间的距离 (x1, y1) (x2, y2)
将闭包与函数之间做对比
"""
import math
def func_dist(x1, y1, x2, y2):
""" 函数方式 """
return math.sqrt(((x1 - x2) ** 2) + ((y1 - y2) ** 2))
def outer_func_dist(x1, y1):
""" 闭包方式 """
def inner_func_dist(x2, y2):
return math.sqrt(((x1 - x2) ** 2) + ((y1 - y2) ** 2))
return inner_func_dist
"""
计算点(10,10) 和点(20, 20) 分别距原点(0, 0) 之间的距离
"""
distance1 = func_dist(0, 0, 10, 10)
distance2 = func_dist(0, 0, 20, 20)
print("点(10, 10) 与原点间的距离:{}".format(distance1))
print("点(20, 20) 与原点间的距离:{}".format(distance2))
print("==" * 22)
inner_func_dist = outer_func_dist(0, 0)
distance3 = inner_func_dist(10, 10)
distance4 = inner_func_dist(20, 20)
print("点(10, 10) 与原点间的距离:{}".format(distance3))
print("点(20, 20) 与原点间的距离:{}".format(distance4))
闭包高级使用
使用闭包在不修改源代码的情况下,添加新的功能
符合开闭原则
""""
闭包的高级用法:
使用闭包在不修改源代码的情况下,添加新的功能
开闭原则: 对修改关闭,对增加新功能开放
"""
import time
def writeLog(func):
"""
在调用其他函数时,记录函数的名称,以及调用的时间
"""
with open('log.txt', 'a', encoding='utf-8') as file:
file.write(func.__name__)
file.write('\t')
file.write(time.asctime())
file.write('\n')
def outer_func(func):
""" 采用闭包方式 ,"""
def funcIn():
writeLog(func)
func()
return funcIn
def fun1():
# writeLog(fun1)
print("我是功能1 ...")
def fun2():
# writeLog(fun2)
print("我是功能2 ...")
fun1 = outer_func(fun1)
fun2 = outer_func(fun2)
fun1()
fun2()
装饰器模式
通常与闭包紧密结合使用, 简化了闭包函数的调用
使用: @闭包外部函数名,将其放在指定的函数头上即可
""""
闭包的高级用法:
使用闭包在不修改源代码的情况下,添加新的功能
开闭原则: 对修改关闭,对增加新功能开放
装饰器: 通常与闭包紧密结合使用
"""
import time
def writeLog(func):
"""
在调用其他函数时,记录函数的名称,以及调用的时间
"""
with open('log.txt', 'a', encoding='utf-8') as file:
file.write(func.__name__)
file.write('\t')
file.write(time.asctime())
file.write('\n')
def outer_func(func):
""" 采用闭包方式 ,"""
def funcIn():
writeLog(func)
func()
return funcIn
# 装饰器
@outer_func
# fun1 = outer_func(fun1)
def fun1():
# writeLog(fun1)
print("我是功能1 ...")
@outer_func
# fun2 = outer_func(fun2)
def fun2():
# writeLog(fun2)
print("我是功能2 ...")
# fun1 = outer_func(fun1)
# fun2 = outer_func(fun2)
fun1()
fun2()
通用装饰器
解决不同函数中参数个数不一致,而导致闭包中参数传递问题
格式
def funcOut(func):
""" 闭包的格式 """
def funcIn(*args, **kwargs):
# 这里调用其他函数
func(*args, **kwargs)
return funcIn
测试
"""
通用装饰器:解决不同函数的参数个数不同(通过可变参数实现)
"""
def add_new_fun():
print("我是新功能哦!")
def funcOut(func):
""" 通用装饰器"""
def funcIn(*args, **kwargs):
add_new_fun()
func(*args, **kwargs)
return funcIn
def funcOut1(func):
""" 闭包函数 1"""
def funcIn(x, y):
add_new_fun()
func(x, y)
return funcIn
def funcOut2(func):
""" 闭包函数 2"""
def funcIn(x, y, z):
add_new_fun()
func(x, y, z)
return funcIn
# @funcOut1
@funcOut
def func1(a, b):
print("a={},b={}".format(a, b))
@funcOut
# @funcOut2
def func2(a, b, c):
print("a={},b={},c={}".format(a, b, c))
if __name__ == '__main__':
func1(1, 2)
func2(1, 2, 3)
Python 语言特性
动态添加属性
动态语言:可以在运行时,改变类的结构,添加属性,添加方法,删除函数
强类型语言: 变量的类型,运行时决定。
变量的类型在运行之后, 可以任意变量,不需要强制转换
添加对象属性 | 添加类属性 |
---|---|
对象名.属性 | 类名.属性 |
setattr(对象名, 属性, 属性名) |
"""
Python 是动态语言:
可以动态地添加对象的属性、类属性、对象方法
Python 也是强类型语言
"""
class Student:
""" 学生类 """
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return "Student:name:{},age:{}".format(self.name, self.age)
if __name__ == '__main__':
marry = Student('marry', 20)
print(marry)
"""
动态地增加对象的属性
"""
# 方式1
marry.score = 90
print(marry, "score:{}".format(marry.score))
# 方式2,通过 setattr 内置函数为 marry 对象设置 addr 属性,值为 安徽
setattr(marry, 'addr', '安徽')
print(marry, "address:{}".format(marry.addr))
"""
动态地类属性
"""
Student.clz = "七班"
print("班级:%s" % Student.clz)
"""创建 tom 对象"""
tom = Student("tom", 25)
print(tom)
动态添加方法
添加方法 | 实现 |
---|---|
添加对象(成员)方法 | types.MethodType(函数名, 对象名) |
添加静态方法 | 类名.方法名 = 函数名 @staticmethod |
添加类方法 | 类名.方法名 = 函数名 @classmethod |
注意: 函数名不要加括号
"""
添加动态属性
导入 types 库
"""
import types
class Student:
""" 学生类 """
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return "Student:name:{},age:{}".format(self.name, self.age)
if __name__ == '__main__':
tom = Student("tom", 24)
"""
为对象绑定动态方法
"""
def getName(self):
return self.name
# 将方法 getName 绑定到 tom 对象上
tom.getName = types.MethodType(getName, tom)
print("Name:{}".format(tom.getName()))
"""
添加静态方法
"""
@staticmethod
def study():
print("学习使我快乐, 我爱学习!")
# 绑定静态方法
Student.study = study
# 调用静态方法
tom.study()
Student.study()
""" 添加类方法"""
@classmethod
def playGame(cls):
print("我爱游戏 ...")
Student.playGame = playGame
# 调类方法
Student.playGame()
"""
创建 marry 对象
"""
marry = Student('marry', 25)
marry.study()
marry.playGame()
__slots__
的作用
限制作用:对添加对象属性和方法有限制,但是对类属性和方法、静态方法以及子类没有限制
"""
添加动态属性
导入 types 库
"""
import types
class Student:
""" 学生类 """
__slots__ = ('name', 'age')
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return "Student:name:{},age:{}".format(self.name, self.age)
class LitteStudent(Student):
pass
if __name__ == '__main__':
tom = Student("tom", 24)
# tom.score = 100 # 'Student' object has no attribute 'score'
"""
为对象绑定动态方法
"""
def getName(self):
return self.name
# 将方法 getName 绑定到 tom 对象上
# tom.getName = types.MethodType(getName, tom)
# print("Name:{}".format(tom.getName())) #'Student' object has no attribute 'getName'
"""
添加静态方法
"""
@staticmethod
def study():
print("学习使我快乐, 我爱学习!")
# 绑定静态方法
Student.study = study
# 调用静态方法
tom.study()
Student.study()
""" 添加类方法"""
@classmethod
def playGame(cls):
print("我爱游戏 ...")
Student.playGame = playGame
# 调类方法
Student.playGame()
"""
创建 marry 对象
"""
marry = Student('marry', 25)
marry.study()
marry.playGame()
"""
創建 litteStudent 对象
"""
lStudent = LitteStudent("小学生", 12)
lStudent.score = 100
lStudent.getName = types.MethodType(getName, lStudent)
print(lStudent)
print(lStudent.getName())
函数式编程
range 函数
"""
range 函数学习
1. range(end)
2. range(start[, end, step])
start: 表示开始位置
end: 表示结束位置(不包括结束位置的元素)
step: 表示步长
"""
if __name__ == '__main__':
list1 = [_ for _ in range(10)]
print(list1)
for i in range(1, 11, 2):
print(i, end=" ")
print() # 换行
for i in range(11, 0, -2):
print(i, end=" ")
partial 偏函数
python 中提供一种用于对函数固定属性的函数
使用:导入 functools
"""
使用偏函数,简化对其他函数的调用的传参问题
"""
from functools import partial
# 定义一个函数
def str_to_decimal(bin_str, base=2):
return int(bin_str, base)
if __name__ == '__main__':
""" 将二进制的字符串转为 10 进制的数字"""
binary_str = '0111'
num = int(binary_str, 2)
# 方式 1
print("int 转化后的数字:{}".format(num))
# 方式 2
str_to_decimal(binary_str)
print("int 转化后的数字:{}".format(num))
# 方式 3
int2 = partial(int, base=2)
num = int2(binary_str)
print("int 转化后的数字:{}".format(num))
wraps 函数
functools.wraps 可以原函数对象的指定属性复制给包装函数对象,默认有 mouble、name、doc或者通过参数选择
解决问题:解决原函数被装饰器装饰后,原函数的文档注释不能打印
"""
wraps:
"""
from functools import wraps
from time import asctime
def write_log(func):
""" 打印函数 func 的名字以及被调用的时间"""
print("{} is calling ...time:{}".format(func.__name__, asctime()))
pass
def funcOut(func):
"""外部函数"""
# 使用 wraps
@wraps(func)
def funcIn(*args, **kwargs):
"""内部函数"""
write_log(func)
return func(*args, **kwargs)
return funcIn
@funcOut
# test = funcOut(test)
def test(x):
"""计算 x 的平方"""
return x ** 2
if __name__ == '__main__':
result = test(3)
print("result: {}".format(result))
print(test.__name__)
print(test.__doc__)
map 内置函数
生成一个迭代器
"""
map 函数:生成一个迭代器,它使用计算 可迭代性的参数的函数,当最短的可迭代性的长度不够时停止(我的翻译)
创建一个迭代器,它使用来自每个迭代器的参数来计算函数。当最短的迭代器耗尽时停止。(有道翻译)
Make an iterator that computes the function using arguments from
each of the iterables. Stops when the shortest iterable is exhausted.
"""
def test(a):
return a + 1
def test2(a, b):
return a + b
if __name__ == '__main__':
list1 = [1, 2, 3]
list2 = [2, 4, 6, 8]
# 生成一个迭代器
# generator1 = map(test, list1)
generator1 = map(lambda x: x + 1, list1)
print([x for x in generator1]) # [2, 3, 4]
print("======================")
# 再生成一个迭代器
# generator2 = map(test2, list1, list2)
generator2 = map(lambda x, y: x + y, list1, list2)
# 1+2 2+4 3+6
print([x for x in generator2]) # [3, 6, 9]
reduce 函数
使用: functools.reduce
应用场景: 遍历求和
"""
reduce 函数: 循环求和
"""
from random import randint
from functools import reduce
def generate_random_list(num):
""" 生成 num 个随机数,并放入列表中"""
return [randint(1, 100) for _ in range(num)]
def sum_list(list1):
""" 计算 list1 列表中的和 """
sum = 0
for i in list1:
sum += i
return sum
if __name__ == '__main__':
list1 = generate_random_list(5)
print(list1)
result = sum_list(list1)
print(result)
result2 = reduce(lambda x, y: x + y, list1)
print(result2)
filter 内置函数
过滤列表中不符合条件的元素, 并返回一个可迭代对象
"""
filter 内置函数
Return an iterator yielding those items of iterable for which function(item)
is true. If function is None, return the items that are true.
"""
from collections import Iterable
def test(list1):
""" 将列表中能够被 2 整除的数放入新的列表中并返回 """
list2 = []
for i in list1:
if i % 2 == 0:
list2.append(i)
return list2
if __name__ == '__main__':
list1 = [1, 2, 0, 0, 5, 9, 8]
print("使用 test 函数:", test(list1))
result1 = filter(None, list1) # 保留返回值为 True 的元素
print("result1:", [_ for _ in result1])
result2 = filter(lambda x: x % 2 == 0, list1) # 返回可迭代对象
print("具有可迭代性:", isinstance(result2, Iterable))
print("result2:", [x for x in result2])
sorted() 内置函数
分类 | 作用 |
---|---|
list.sort() | 无返回值, 对原列表数据进行排序 |
sorted(list[,key=自定义排序条件,reserse={True,False}]) | 有返回值, 返回一个新列表 |
"""
list.sort() 对原列表进行排序,不产生新的列表
sorted() 对原列表排序后,返回新的列表
"""
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return "Student[name:{},age{}]".format(self.name, self.age)
if __name__ == '__main__':
list1 = [1, 11, 3, 9, 3, 7, 2]
# list1.sort()
print(list1)
list2 = sorted(list1)
print("list2:", list2)
list3 = sorted(list1, reverse=True) # 倒序排列
print("list3:", list3)
list5 = [1, 5, 4, 9, -9, -27, -1, 0]
list6 = sorted(list5, key=lambda x: x < 0 and abs(x))
print("list6:", list6)
print("============================")
tom = Student('Tom', 14)
marry = Student('Marry', 15)
jenny = Student('Jenny', 16)
stuList = [tom, marry, jenny]
for stu in stuList:
print(stu)
print("==============================")
# sorted_stuList = sorted(stuList, key=lambda stu: stu.name)
sorted_stuList = sorted(stuList, key=lambda stu: stu.age, reverse=True)
for stu in sorted_stuList:
print(stu)
正则表达式
正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串
re 模块
match 基本使用
语法
"""
match(匹配的规则字符串, 目标子符串)
"""
from re import match, search
if __name__ == '__main__':
pattern = "hello"
str1 = "hell1word hello"
# result = match(pattern, str1)
result = search(pattern, str1)
print(type(result))
print(result)
# print(result.span()) # 返回查找到字符串的索引
# print(result.group()) # 返回查找到字符串的列表
表示字符
字符 | 功能 |
---|---|
. | 匹配任意一个字符 |
[] | 匹配列表中的字符 |
\d | 匹配数字, 即0-9 |
\D | 匹配非数字 |
\s | 匹配空白,即空格(\n\t) |
\S | 匹配非空格 |
\w | 匹配单词字符, 即 a-z,A-Z,0-9,_等 |
\W | 匹配非单词字符 |
import re
v = re.match('.','a')
v = re.match('.','1')
v = re.match('.','_')
#返回None
v = re.match('.','\n')
print(v)
v = re.match('\d','1')
print(v)
v = re.match('\D','a1')
print(v)
v = re.match('\s',' ')
v = re.match('\s','\n')
v = re.match('\s','\t')
print(v)
#非空格
v = re.match('\S',' ')
print(v)
v = re.match('\w','a')
v = re.match('\w','A')
v = re.match('\w','1')
v = re.match('\w','_')
print(v)
v = re.match('\W','a')
v = re.match('\W','A')
v = re.match('\W','1')
v = re.match('\W','_')
print(v)
v = re.match('\w\W','1a')
print(v)
表示数量
数量 | 说明 |
---|---|
* | 匹配前0个或多个(可有可无) |
+ | 匹配前1个或多个 |
? | 匹配前1个(可有(有只出现一次)可无) |
{n} | 匹配前字符出现 n 次 |
{n,} | 匹配前字符至少出现 n 次 |
{n,m} | 匹配前字符出现 m 次到 n 次,限定字符的位数 |
"""
使用正则表达式表示数量:
*匹配前0个或多个(可有可无)
+匹配前1个或多个
?匹配前1个(可有(有只出现一次)可无)
{n}匹配前字符出现 n 次
{n,}匹配前字符至少出现 n 次
{n,m}匹配前字符出现 m 次到 n 次,限定字符的位数
"""
import re
if __name__ == '__main__':
# pattern = "\d*"
# pattern = "\d+"
# pattern = "\d?"
pattern = "\d{2,4}"
s = "123123ab"
# s = ""
s = "21abc"
# v = re.match(pattern, s)
# print(v)
# 匹配手机号
pattern = "1[348]\d{9}"
s = "13345678901"
# print(re.match(pattern, s))
# 匹配变量名 (大写,小写,数字,下划线,只能以字母和下划线开头)
pattern = "[a-zA-Z_]\w*"
var = "H_hello_123"
# print(re.match(pattern, var))
# 匹配数字 1-99
pattern = "[1-9][0-9]?"
num = "0"
num = "9"
num = "99"
print(re.match(pattern, num))
# 用户名由字母、数字、下划线组成,位数 5,10位之间
pattern = "[a-zA-Z_]{5,10}"
s = "_abcaa1111"
print(re.match(pattern, s))
原始字符串
Python 中字符串前边加 r 表示原生字符串
"""
原始字符串
"""
import re
if __name__ == '__main__':
s = '\n123'
print(s)
s = r'\n123'
print(s)
s = '\\n123'
print(s)
# pattern = '\\\\n\d{3,}'
pattern = r'\\n\d{3,}'
v = re.match(pattern, s)
print(v)
边界
字符 | 功能 |
---|---|
^ | 匹配字符串开头 |
$ | 匹配字符串结尾 |
\b | 匹配一个单词的边界 |
\B | 匹配非单词的边界 |
"""
边界
"""
import re
if __name__ == '__main__':
# $ 表示匹配结尾
# 匹配 163 邮箱
pattern = "1[389]\w{9}@163.com$"
s = "13856123451@163.com"
print(re.match(pattern, s))
# \b 匹配单词结尾
pattern = r"\w*er\b"
pattern = r"\bHello_\w*"
pattern = r"\bhttp://www.\w*.com"
s = "zwzwer"
s = "Hello_1232ljj"
s = "https://www.baidu.com"
print(re.match(pattern, s))
分组
字符 | 功能 |
---|---|
丨 | 匹配左右任意一个表达式 |
(ab) | 将括号中的字符作为一个分组 |
\num | 引用分组num匹配到的字符串 |
(?p<name>) | 分别起组名 |
(?p=name) | 引用别名为name分组匹配到的字符串 |
-
匹配 [0,100] 之间的数
pattern = r"[1,9]?\d$|100$" # 注意: | 前后不能有空格,否则当做匹配的规则 s = "0" s = "99" s = "100" v = re.match(pattern, s) print(v)
-
匹配数字 0001-11233
pattern = r"(\d{4})-([1-9]\d{4})$"
s = "0001-11111"
v = re.match(pattern, s)
print(v)
print(v.group())
print(v.group(1))
print(v.group(2))
print(v.groups())
匹配 <html><title>我是标题哈</title></html>
# pattern = r"<.+><.+>.+</.+></.+>"
pattern = r"<(.+)><(.+)>.+</\2></\1>"
# s = "<html><title>我是标题哈</head></body>"
s = "<html><title>我是标题哈</title></html>"
v = re.match(pattern, s)
print(v)
print(v.group())
print(v.group(1))
print(v.group(2))
print(v.groups())
-
匹配 <h2><font>我是2级标题</font></h2>
pattern = "<(?P<h>.+)><(?P<font>.+)>.+</(?P=font)></(?P=h)>" s = "<h2><p>我是2级标题</p></h2>" v = re.match(pattern, s) print(v) print(v.group()) print(v.groups()) print(v.group('h')) print(v.group('font'))
正则表达式高级用法
方法 | 作用 |
---|---|
match | 从目标字符串的开头进行匹配 |
search | 遍历目标字符串,查找第一个符合匹配规则的子串 |
findall | 遍历目标字符串,查找所有符合匹配规则的子串 |
sub | 遍历目标字符串,查找所有符合匹配规则的子串并替换 |
split | 按照匹配规则,分割目标字符串为列表 |
"""
match:从目标字符串的开头,进行匹配
search: 遍历目标字符串,查找第一个符合匹配规则的子符串
findall: 遍历目标字符串,查找所有符合匹配规则的子符串
sub: 遍历目标字符串,查找所有符合匹配规则的子符串并替换
split: 按照匹配规则,分割目标字符串为列表
"""
import re
if __name__ == '__main__':
s = "点赞量为:99次,转发量为:10次,评论数为:9次"
pattern = r"\d+"
v = re.search(pattern, s)
print(v)
list1 = re.findall(pattern, s)
print(list1)
print("======================s")
"""
字符串替换
"""
def replace(result):
""" 替换匹配成功字串内容 """
# print(result)
# print(result.group())
return str(int(result.group()) + 10)
# count=0 表示替换所有符合条件的子串
# count=1 表示替换第一次匹配成功后,替换该子串,后面符合条件的字串不替换
# count=n(n>=1) 表示替换前n次匹配成功后,替换该子串,后面符合条件的字串不替换
# new_str = re.sub(pattern, '100', s, count=2)
new_str = re.sub(pattern, lambda x: str(int(x.group()) + 10), s, count=2)
print(new_str)
print("======================")
"""
根据正则表达式拆分字符串
"""
test = "HelloWorld!Python:大法好;优秀 哈"
list_split = re.split(r'\s|!|:|;', test)
print(list_split)
贪婪模式与非贪婪模式
- 什么是贪婪模式?
- Python里数量词默认是贪婪的, 总是尝试匹配尽可能多的字符
- 什么是非贪婪
- 与贪婪相反,总是尝试匹配尽可能少的字符,可以使用"*","?","+","{m,n}"后面加上?,使贪婪变成非贪婪
"""
贪婪模式: 默认是贪婪模式,在满足条件的前提下,尽可能多的匹配子串
非贪婪模式: 增加 ? ,在满足条件的前提下,尽可能少的匹配子串
"""
from re import match
if __name__ == '__main__':
# 匹配 My telephone is 011-1232-1231
s = "My telephone is 011-1232-1231"
pattern = "(.+?)(\d+)-(\d+)-(\d+?)"
v = match(pattern, s)
print(v.group())
print(v.groups())
s = "aaabb123"
pattern = r"(\w+?)([1-9]+)"
v = match(pattern, s)
print(v.group())
print(v.groups())
内存管理
元类
类也是对象(属于元类的对象)
"""
type 内置函数的作用:
1. 查看对象的数据类型
2. 动态创建类,语法格式 type(类名, (父类,), {属性或方法})
"""
class Animal:
def __init__(self, name):
self.name = name
def shut(self):
print("动物叫 ....")
def dog_shut(self):
print("dog 汪汪汪 ...")
if __name__ == '__main__':
def work(self):
print("捏土造人...")
Person = type('Person', (), {'name': '女娲', 'work': work})
print("查看 Person类 的继承结构:", Person.mro())
nvwa = Person()
print("name:", nvwa.name)
nvwa.work()
print("==================")
Dog = type('Dog', (Animal, ), {'age':10, 'dog_shut':dog_shut})
dog = Dog("小黑狗")
dog.dog_shut()
print(dog.name)
dog.shut()
print("查看 Dog 的继承结构:", Dog.mro())
类装饰器
在不修改函数源代码的前提下,增加新的功能
"""
类装饰器的使用:
在不修改函数源代码的情况下,增加新的功能,如记录日志,权限管理
"""
class CC:
def __init__(self, func):
print("CC.__init__ 方法被调用了 ...")
print(func.__name__)
self.__func = func
# 解决 TypeError: 'CC'object is not callable
def __call__(self, *args, **kwargs):
self.addFunc() # 调用自己的方法在函数调用之前
self.__func() # 被装饰的函数
def addFunc(self):
print("我是 CC 类中的新功能 ...")
@CC
# 添加类装饰提起 @CC ,等价于执行 test = CC(test)
def test():
print("我是功能 test")
if __name__ == '__main__':
test()
对象池
什么叫做垃圾回收?
生活案例
-
小整数池
- 系统默认创建好的,等着你使用
- 概述
整数在程序中的使用非常广泛,Python为了优化速度,使用了小整数对象池,
避免为整数频繁申请和销毁内存空间。Python 对小整数的定义是 [-5, 256]
这些整数对象是提前建立好的,不会被垃圾回收。在一个 Python 的程序中,
无论这个整数处于LEGB(局部变量,闭包,全局,内建模块)中的哪个位置,
所有位于这个范围内的整数使用的都是同一个对象。
案例:(必须使用终端验证,pycharm每次都是所有代码都加载到内存中, 被看成是一个整体) 代码验证小整数 a = 100 print(id(a)) del a b = 100 print(id(b)) 发现删除a后,b的地址依旧是删除之前的那个地址(是否删除,小整数都常驻内存)
-
大整数池
默认创建出来,池内为空的,创建一个就会往池中存储一个 -
intern机制
- 每个单词(字符串),不夹杂空格或者其他符号,默认开启intern机制,共享内存,靠引用计数决定是否销毁
案例验证: a = 'HelloWorld' b = 'HelloWorld' print(a is b) a = 'Hello World' b = 'Hello World' print(a is b)
- c.对象被引用 ``` stu2 = stu ``` - d.将对象作为参数,传入某个函数 ``` func(stu) ```
-
减少对象引用计数的情况
-
a.对象被显示销毁
del stu
-
b.对象名指向新的对象
stu = Student()
-
c.从容器中移除,或者显示销毁列表
list1.remove(stu) list1.pop(stu)
-
d.局部变量对象,作为函数参数,
函数结束时,引用计数-1
-
获取某个对象的引用计数
import sys obj = 'Helloworld' sys.getrefcount(obj) list1 = [] list.append(obj) sys.getrefcount(obj)
-
垃圾收集
现在的高级语言如java,c#等,都采用了垃圾收集机制,
而不再是c,c++里用户自己管理维护内存的方式。自己管理内存极其自由,
可以任意申请内存,但如同一把双刃剑,为大量内存泄露,悬空指针等bug埋下隐患。
python里也同java一样采用了垃圾收集机制,不过不一样的是:
python采用的是引用计数机制为主,标记-清除和分代收集两种机制为辅的策略
- 引用计数
python里每一个东西都是对象,它们的核心就是一个结构体:PyObject
typedef struct_object {
int ob_refcnt;
struct_typeobject *ob_type;
} PyObject;
PyObject是每个对象必有的内容,其中ob_refcnt就是做为引用计数。
当一个对象有新的引用时,它的ob_refcnt就会增加,当引用它的对象被删除,它的ob_refcnt就会减少
#define Py_INCREF(op) ((op)->ob_refcnt++) //增加计数
#define Py_DECREF(op) \ //减少计数
if (--(op)->ob_refcnt != 0) \
; \
else \
__Py_Dealloc((PyObject *)(op))
当引用计数为0时,该对象生命就结束了。
-
引用计数机制的优点:
- 1.简单
- 2.实时性:一旦没有引用,内存就直接释放了。不用像其他机制等到特定时机。
实时性还带来一个好处:处理回收内存的时间分摊到了平时。
-
引用计数机制的缺点:
- 1.维护引用计数消耗资源
- 2.循环引用的问题无法解决(DOS窗口,查看内存tasklist,或者内存表,任务管理器)
案例: import gc class AAA(object): def __init__(self): print ("object: born at:%s"%hex(id(self))) def __new__(cls, *args, **kwargs): print ("new") return super(AAA, cls).__new__(cls) def __del__(self): print ("bye bye") def start(): while True: a = AAA() b = AAA() a.v = b b.v = a #无法删除 del a del b gc.disable() start()
-
隔代回收
分代回收是用来解决交叉引用(循环引用),并增加数据回收的效率. 原理:通过对象存在的时间不同,采用不同的算法来 回收垃圾. 形象的比喻, 三个链表,零代链表上的对象(新创建的对象都加入到零代链表),引用数都是一,每增加一个指针,引用加一,随后python会检测列表中的互相引用的对象,根据规则减掉其引用计数. GC算法对链表一的引用减一,引用为0的,清除,不为0的到链表二,链表二也执行GC算法,链表三一样. 存在时间越长的数据,越是有用的数据
- 隔代回收触发时间?(GC阈yu值)
随着你的程序运行,Python解释器保持对新创建的对象, 以及因为引用计数为零而被释放掉的对象的追踪。从理论上说, 这两个值应该保持一致,因为程序新建的每个对象都应该最终被释放掉。 当然,事实并非如此。因为循环引用的原因,从而被分配对象的计数值 与被释放对象的计数值之间的差异在逐渐增长。一旦这个差异累计超过某个阈值, 则Python的收集机制就启动了,并且触发上边所说到的零代算法, 释放“浮动的垃圾”,并且将剩下的对象移动到一代列表。 随着时间的推移,程序所使用的对象逐渐从零代列表移动到一代列表。
而Python对于一代列表中对象的处理遵循同样的方法,一旦被分配计数值
与被释放计数值累计到达一定阈值,Python会将剩下的活跃对象移动到二代列表。
通过这种方法,你的代码所长期使用的对象,那些你的代码持续访问的活跃对象,
会从零代链表转移到一代再转移到二代。通过不同的阈值设置,Python可以在
不同的时间间隔处理这些对象。Python处理零代最为频繁,其次是一代然后才是二代。
```
- 查看引用计数
-
gc模块的使用
常用函数: 1、gc.get_count() 获取当前自动执行垃圾回收的计数器,返回一个长度为3的列表 2、gc.get_threshold() 获取gc模块中自动执行垃圾回收的频率 3、gc.set_threshold(threshold0[,threshold1,threshold2]) 设置自动执行垃圾回收的频率 4、gc.disable() python3默认开启gc机制,可以使用该方法手动关闭gc机制 5、gc.collect() 手动调用垃圾回收机制回收垃圾
-
增加引用计数的条件
-
a.创建对象
stu = Student()
-
b.将对象加入列表
list1.append(stu)
-
c.对象被引用
stu2 = stu
-
d.将对象作为参数,传入某个函数
func(stu)
-
-
减少对象引用计数的情况
-
a.对象被显示销毁
del stu
-
b.对象名指向新的对象
stu = Student()
-
c.从容器中移除,或者显示销毁列表
list1.remove(stu) list1.pop(stu)
-
d.局部变量对象,作为函数参数,
函数结束时,引用计数-1
-
获取某个对象的引用计数
import sys obj = 'Helloworld' sys.getrefcount(obj) list1 = [] list.append(obj) sys.getrefcount(obj)
-
-
测试代码
- 引用计数机制
"""
内存管理 --- > 垃圾回收
1. 引用计数(为主)
添加计数: 创建对象, 一个对象的引用为 2
变量引用 +1
添加集合 lsit 、tuple 、 dict 、set +1
函数调用 加 +2
减少计数:
del 对象名
变量引用更换
list.remove
函数调用结束
缺点;相互引用,引用计算无法删除类似的对象
2. 分代回收(为辅)
原理:
随着时间的推进,程序用于冗(rong)余对象逐渐增多,达到一定数量(阈(yu)值,系统进行回收)
"""
import sys
def test(aa):
print(aa)
print("a 对象的引用计数为:", sys.getrefcount(a))
class AA(object):
""" 测试类 """
def __new__(cls, *args, **kwargs):
""" 创建实例 """
print("AA __new___ 创建对象")
return super(AA, cls).__new__(cls)
def __init__(self):
""" 对象创建好之后初始化变量 """
print("AA.__init__ 初始化 ...")
print("object: born at:", hex(id(self)))
def __del__(self):
""" 在对象被销毁下调用 """
print("say bye bye!!!")
if __name__ == '__main__':
"""
引用计数测试测试
"""
a = AA()
print("a 对象的引用计数为:", sys.getrefcount(a))
b = a
print("a 对象的引用计数为:", sys.getrefcount(a))
list1 = [a]
print("a 对象的引用计数为:", sys.getrefcount(a))
del b
print("a 对象的引用计数为:", sys.getrefcount(a))
list1.remove(a)
print("a 对象的引用计数为:", sys.getrefcount(a))
test(a)
print("a 对象的引用计数为:", sys.getrefcount(a))
print("=========== 程序结束 =============")
- 分代垃圾回收
"""
垃圾分代回收; 解决引用计数机制的循环引用问题
gc.get_threshold()
gc.get_count()
gc.set_threshold(200, 10, 10)
threshold: (700, 10, 10)
"""
import gc, time
class AA(object):
def __new__(cls, *args, **kwargs):
""" 对象创建 ...."""
return super(AA, cls).__new__(cls)
def __init__(self):
""" 对象初始化 ..."""
print("object: born at", hex(id(self)))
def __del__(self):
print("被系统回收了,", hex(id(self)))
def start():
while True:
a = AA()
b = AA()
a.v = b # 动态为类创建成员属性
b.v = a # 动态为类创建成员属性
del a
del b
print("threshold:", gc.get_threshold()) # 分代(0 1 2)阈值
print("count:", gc.get_count()) # 当前垃圾
time.sleep(0.1)
if __name__ == '__main__':
# gc.disable() # 关闭垃圾回收
gc.set_threshold(200, 10, 10)
start()
内建函数
-
什么叫内建函数:
启动python解释器后,默认加载的函数称为内建函数
-
如何查看内建函数
两种方式: a. dir(__builtins__) b. import builtins dir(builtins)
-
常用内建函数:
-
range()
python range() 函数可创建一个整数列表,一般用在 for 循环中。 语法: range(start, stop[, step]) 参数说明: start: 计数从 start 开始。默认是从 0 开始。例如range(5)等价于range(0, 5); stop: 计数到 stop 结束,但不包括 stop。例如:range(0, 5) 是[0, 1, 2, 3, 4]没有5 step:步长,默认为1。例如:range(0, 5) 等价于 range(0, 5, 1) 返回:range 案例: 代码验证
-
map()
map() 会根据提供的函数对指定序列做映射。 第一个参数 function 以参数序列中的每一个元素调用 function 函数, 返回包含每次 function 函数返回值的新列表。 语法: map(function, iterable, ...) 参数说明: function -- 函数 iterable -- 一个或多个序列 返回: Python 2.x 返回列表。 Python 3.x 返回迭代器。 案例: from collections import Iterable from collections import Iterator def func(x,y): return x*y # 使用匿名函数 v = map(lambda x:x*2,[1,2,3]) print(type(v)) print(isinstance(v,Iterable)) print(isinstance(v,Iterator)) for x in v: print(x) # 两个参数 v1 = map(func,[1,2,3],[4,5,6]) v2 = list(v1) print(type(v2))
-
filter()
filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。 该接收两个参数,第一个为函数,第二个为序列, 序列的每个元素作为参数传递给函数进行判断,然后返回 True 或 False, 最后将返回 True 的元素放到新列表中。 语法: filter(function, iterable) 参数说明: function -- 判断函数。 iterable -- 可迭代对象。 返回: 返回迭代器。 案例: def func2(x): return x % 2 == 0 # 找出1-100中的偶数 list2 = filter(func2,[x for x in range(1,100)]) print(isinstance(list2,Iterator)) for x in list2: print(x)
-
reduce()
3.x后,需要先from functools import reduce reduce() 函数会对参数序列中元素进行累积。 函数将一个数据集合(链表,元组等)中的所有数据进行下列操作: 用传给reduce中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作, 得到的结果再与第三个数据用 function 函数运算,最后得到一个结果。 语法: reduce(function, iterable[, initializer]) 参数说明: function -- 函数,有两个参数 iterable -- 可迭代对象 initializer -- 可选,初始参数 返回: 返回函数计算结果 案例:求列表所有值的和 from functools import reduce v = reduce(lambda x,y:x+y,[1,2,3,4],5) print(v) v = reduce(lambda x,y:x+y,['1','2','3','4'],'5') print(v) 案例: 求列表中数字所能表示的整型数 -------------------- def func_4(x,y): return x * 10 + y list3 = [1,2,3,4] value = reduce(func_4,list3) print(value)
-
sorted()
sorted() 函数对所有可迭代的对象进行排序操作。 sort 与 sorted 区别: sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。 list 的 sort 方法返回的是对已经存在的列表进行操作, 而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作 语法: sorted(iterable[, key[, reverse]]) 参数说明: iterable -- 可迭代对象。 key -- 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。 reverse -- 排序规则,reverse = True 降序 , reverse = False 升序(默认) 返回: 返回重新排序的列表。 案例: class Student(): def __init__(self,name,age): self.name = name self.age = age def __str__(self): return self.name+str(self.age) students = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)] # 根据 students = sorted(students,key=lambda s:s[1]) print(students) students = [Student('jj',12),Student('dd',19),Student('xx',32)] # 自定义对象的排序 students1 = sorted(students,key=lambda x:x.name) for s in students1: print(s)
常见面试题: list1 = [-2,3,0,20,2,-5] c = sorted(list1,key=lambda x:(x<0,abs(x))) print(c)
-
偏函数
-
概念:
- python 中提供一种用于对函数固定属性的函数
-
定义:
from functools import partial int3 = partial(int,base=2) print(int3('1010'))
-
作用:
- 把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单
-
案例:
str1 = '1010' result = int(str1,2) print(result) #使用传统函数 def int2(n,base = 2): return int(n,base) print(int2('1010')) #使用片函数 int3 = partial(int,base=2) print(int3('1010'))
wraps
-
作用:
- functools.wraps 可以将原函数对象的指定属性复制给包装函数对象, 默认有 module、name、doc,或者通过参数选择
-
使用:
def log(func): # @wraps(func) def with_logging(*args,**kwargs): print("%s was calling"%func.__name__) return func(*args,**kwargs) return with_logging @log def test(x): """return x << 2""" return x * x print(test.__name__) print(test.__doc__)