文章目录
- 版权声明
- property属性
- with语句和上下文管理器
-
- [with语句使用\](#with语句使用)
- 上下文管理器定义
- 生成器
- 浅拷贝和深拷贝
- 正则表达式
版权声明
- 本博客的内容基于我个人学习黑马程序员课程的学习笔记整理而成。我特此声明,所有版权属于黑马程序员或相关权利人所有。本博客的目的仅为个人学习和交流之用,并非商业用途。
- 我在整理学习笔记的过程中尽力确保准确性,但无法保证内容的完整性和时效性。本博客的内容可能会随着时间的推移而过时或需要更新。
- 若您是黑马程序员或相关权利人,如有任何侵犯版权的地方,请您及时联系我,我将立即予以删除或进行必要的修改。
- 对于其他读者,请在阅读本博客内容时保持遵守相关法律法规和道德准则,谨慎参考,并自行承担因此产生的风险和责任。本博客中的部分观点和意见仅代表我个人,不代表黑马程序员的立场。
property属性
-
property() 函数是一种特殊的装饰器,它可以**将一个方法转换为属性,**从而实现对属性的访问和修改。使用 property() 函数可以将类中的方法转换为属性,使得这些属性可以像普通属性一样被访问和修改,但是它们的值是通过方法计算得到的。
-
Python 中,属性通常有两种类型:实例属性和类属性。
- 实例属性是指属于实例的属性,每个实例都有自己的属性值。
- 类属性是指属于类的属性,所有实例共享同一个属性值。
-
使用 property() 函数可以将一个方法转换为实例属性或类属性。
property属性装饰器方式
- @property 表示把方法当做属性使用, 表示当获取属性时会执行下面修饰的方法
- @方法名.setter 表示把方法当做属性使用,表示当设置属性时会执行下面修饰的方法
- 装饰器方式的property属性修饰的方法名一定要一样
python
class Person(object):
def __init__(self):
self.__age = 0
# 获取属性
@property
def age(self):
return self.__age
# 修改属性
@age.setter
def age(self, new_age):
self.__age = new_age
p = Person()
print(p.age)
# 修改属性
p.age = 100
print(p.age)
property属性类属性方式
python
# 语法
类属性 = property(获取值方法, 设置值方法)
# 使用:
对象.类属性
对象.类属性=值
python
class Person(object):
def __init__(self):
self.__age = 0
def get_age(self):
"""当获取age属性时会使用该方法"""
return self.__age
def set_age(self, new_age):
"""当设置属性时会使用该方法"""
if new_age >= 150:
print("年龄错误")
else:
self.__age = new_age
age = property(get_age, set_age)
p = Person()
print(p.age)
# 设置属性
p.age = 100
print(p.age)
with语句和上下文管理器
with语句使用\
-
with 语句是一种特殊的语法结构,用于处理上下文相关的资源。它可以帮助我们自动分配和释放资源,保证代码的可读性和可靠性。如在文件操作中:简化
try...except...finlally
的处理流程,让读写文件变得更加简洁安全。 -
使用语法:
python
with expression as variable:
# code block
-
expression 表示一个上下文管理器对象,variable 表示一个可选的变量名,用于保存 expression 返回的值。
-
使用 with 语句处理文件读写:
pythonwith open('example.txt', 'w') as f: f.write('Hello, world!')
上下文管理器定义
- 一个类只要实现了
__enter__()
和__exit__()
这个两个方法,这个类就是上下文管理器,通过这个类创建的对象就是上下文管理器对象。enter() 和 exit() 方法,它们分别被 with 语句的上下文管理器对象调用。- enter() 方法在进入代码块之前被调用,用于分配资源和初始化环境。它可以返回一个值,将这个值绑定到
variable
变量上。 - exit() 方法在离开代码块之后被调用,用于释放资源和清理环境。它可以接收三个参数:异常类型、异常对象和异常回溯信息。如果代码块正常执行完成,它们都将为 None。如果代码块中发生了异常,它们将包含相应的信息。
- enter() 方法在进入代码块之前被调用,用于分配资源和初始化环境。它可以返回一个值,将这个值绑定到
python
# 1定义一个File类
class File(object):
def __init__(self, file_name, file_model):
self.file_name = file_name
self.file_model = file_model
# 2实现__enter__() 和 __exit__()方法
def __enter__(self):
print("这是上文")
self.file = open(self.file_name, self.file_model)
return self.file
# 异常类型、异常对象和异常回溯信息
def __exit__(self, exc_type, exc_val, exc_tb):
print("这是下文")
self.file.close()
# 3然后使用 with 语句来完成操作文件
with File("1.txt","r") as f:
file_data = f.read()
print(file_data)
生成器
生成器推导式
-
Python 中的生成器推导式(Generator Expression)是一种快速生成列表、元组、集合和字典的方式。它类似于列表推导式,但是不会一次性生成所有的元素,而是在需要时逐个生成元素,从而节省了内存空间。
-
生成器特点
特点 | 描述 |
---|---|
惰性计算 | 生成器是按需计算的,只有在需要时才会生成下一个元素。 |
节省内存空间 | 生成器不需要事先生成所有元素,因此可以节省大量内存空间,特别是处理大量数据时。 |
可迭代性 | 生成器可以作为可迭代对象,使用 for 循环和其他迭代器方法进行遍历操作。 |
状态保存 | 生成器在每次调用 yield 关键字时会自动暂停并保存当前状态,从而实现高度灵活的数据处理。 |
一次性消耗 | 生成器一般只能被遍历一次,在遍历结束后会被自动消耗。如果需要多次使用生成器的值,可以使用其他数据结构保存。 |
在表格中,列出了生成器的主要特点和描述,使得这些特点更加清晰、简洁和易于理解。使用表格的形式展示生成器特点可以提高信息的可视化程度,有助于读者更加快速和准确地了解生成器的特点。
创建生成器的方式
生成器推导式
-
生成器推导式语法
python(expression for variable in iterable if condition)
- expression 表示一个表达式
- variable 表示一个变量名,用于迭代 iterable 中的元素
- if condition 是一个可选的条件,用于筛选元素。
-
生成器推导式的返回值是一个生成器对象,它可以迭代生成所有符合条件的元素。当需要使用时,可以通过 next() 函数逐个获取元素,或者使用 for 循环语句遍历所有元素。
pythonnums = [1, 2, 3, 4, 5] squares = (x ** 2 for x in nums) print(list(squares)) # [1, 4, 9, 16, 25]
yield 关键字
- yield 关键字:它是在函数中定义生成器的一种方式,它将函数的执行过程暂停并保存当前状态,每次返回一个值,并在下次调用时恢复状态继续执行
- 语法如下
python
def generator_function(arguments):
# code block
yield value
-
只要在函数中使用yield关键字,这个函数就是生成器
-
栗子
python
def generator(num):
for x in range(num):
print("开始")
yield x
print("生成完成")
if __name__ == '__main__':
for i in generator(5):
print(i)
- 栗子说明
- 代码执行到yield会返回结果,下次启动生成器会暂停位置继续向下执行
- 生成器把数据全部生成完成,在向下执行会抛出StopIteration异常
- while循环需要手动处理异常
- for循环内部自动回处理异常
浅拷贝和深拷贝
可变类型和不可变类型
- 可变类型指的是在原有对象上进行修改时,对象的值会发生改变。
- 不可变类型指的是在原有对象上进行修改时,会创建一个新的对象,原有对象的值不会发生改变。
可变类型 | 不可变类型 |
---|---|
列表(list) | 整数(int) |
字典(dict) | 浮点数(float) |
集合(set) | 布尔值(bool) |
自定义对象(class) | 字符串(str) |
元组(tuple) |
- 注意,虽然元组是不可变类型,但是如果元组中包含可变类型的元素,那么这些元素的值可以被修改,因此需要谨慎使用。
浅拷贝
- 浅拷贝使用copy函数, copy只对可变类型的第一层对象进行拷贝,对拷贝的对象开辟新的内存空间进行存储,不会拷贝对象内部的子对象
python
# 2 浅拷贝可变类型
a = [1, 2, 3]
b = [11, 22, 33]
c = [a, b]
d = copy.copy(c)
# 第一层对象进行拷贝,地址不同
print(id(d)) # 2387186757888
print(id(c)) # 2387188259968
# 3 浅拷贝-深层数据
a = [1, 2, 3]
b = [11, 22, 33]
c = [a, b]
d = copy.copy(c)
# 并没有拷贝d的子对象a,地址相同
print(id(a)) # 2387186758272
print(id(c[0])) # 2387186758272
print(id(d[0])) # 2387186758272
-
浅拷贝对不可变类型没有影响,不可变类型进行浅拷贝不会给拷贝的对象开辟新的内存空间,而只是拷贝了这个对象的引用。
python# 浅拷贝不可变类型 a = (1, 2, ["hello", "world"]) b = copy.copy(a) # 查看内存地址 print(id(a)) # 1981560375872 print(id(b)) # 1981560375872
深拷贝
- 深拷贝时候用deepcopy函数,对于可变类型会对该对象到最后一个可变类型的每一层对象就行拷贝, 对每一层拷贝的对象都会开辟新的内存空间进行存储。
python
# 深拷贝可变类型
a = [1, 2, 3]
b = [11, 22, 33]
c = [a, b]
d = copy.deepcopy(c)
print(id(c)) # 1510307470464
print(id(d)) # 1510305968384
# 深拷贝-深层数据
a = [1, 2, 3]
b = [11, 22, 33]
c = [a, b]
d = copy.deepcopy(c)
print(id(a)) # 2505293282880
print(id(c[0])) # 2505293282880
print(id(d[0])) # 2505293247104
-
不可变类型进行深拷贝如果子对象没有可变类型则不会进行拷贝,而只是拷贝了这个对象的引用,否则会对该对象到最后一个可变类型的每一层对象就行拷贝, 对每一层拷贝的对象都会开辟新的内存空间进行存储
python# 深拷贝不可变类型 a = (1, 2, 3) b = (11, 22, 33) c = (a, b) d = copy.deepcopy(c) print(id(c)) # 2468008822784 print(id(d)) # 2468008822784
总结
不可变类型 | 可变类型 | |
---|---|---|
浅拷贝 | 拷贝对象引用,地址相同 | 只拷贝第一层对象,不会拷贝对象内部的子对象 |
深拷贝 | 子对象没有可变类型,拷贝引用 子对象有可变类型,拷贝到最后一个可变对象的每一层 | 拷贝可变类型的每一层对象 |
正则表达式
正则表达式概述
-
正则表达式(Regular Expression),简称正则或RegExp,是一种用来描述、匹配和处理文本的工具。正则表达式通常由一些特殊字符和普通字符组成,用来匹配一定模式的文本。
-
正则表达式在文本处理、数据清洗、文本分析、自然语言处理等领域广泛应用。在Python中,正则表达式被内置在re模块中,可以通过该模块提供的函数来实现正则表达式的匹配和处理。
-
正则表达式的基本语法包括:
- 普通字符:表示匹配该字符本身。
- 特殊字符:表示匹配特定的字符或字符集合。
- 量词符:表示匹配前面的字符出现的次数。
- 边界符:表示匹配字符串的边界。
- 分组:表示将一组字符作为一个整体进行匹配。
- 反向引用:表示引用前面的分组匹配的内容。
常见的符号和语法
符号/语法 | 描述 |
---|---|
. |
匹配任意字符,除了换行符 |
^ |
匹配字符串的开头 |
$ |
匹配字符串的结尾 |
* |
匹配前一个字符零次或多次 |
+ |
匹配前一个字符一次或多次 |
? |
匹配前一个字符零次或一次 |
{n} |
匹配前一个字符恰好出现 n 次 |
{n,} |
匹配前一个字符至少出现 n 次 |
{n,m} |
匹配前一个字符出现 n 到 m 次 |
[...] |
匹配方括号内的任意一个字符 |
[^...] |
匹配不在方括号内的任意一个字符 |
(...) |
创建捕获组,匹配括号内的表达式 |
\d |
匹配任意数字字符 |
\D |
匹配任意非数字字符 |
\w |
匹配任意字母、数字或下划线字符 |
\W |
匹配任意非字母、非数字、非下划线字符 |
\s |
匹配任意空白字符(空格、制表符、换行符等) |
\S |
匹配任意非空白字符 |
(?i) |
忽略大小写匹配 |
(?:...) |
创建非捕获组,不返回匹配的内容 |
(?P<name>...) |
创建具有指定名称的命名捕获组 |
(?P=name) |
引用先前命名捕获组中匹配的内容 |
(?=...) |
正向预查,匹配后面满足条件的位置 |
(?!...) |
负向预查,匹配后面不满足条件的位置 |
这些是正则表达式中常见的符号和语法,用于构建模式以匹配特定的文本模式。使用这些符号和语法,可以创建复杂的匹配规则来搜索、替换或提取文本数据。
re模块介绍
- re模块是Python内置的正则表达式模块,提供了一系列函数来支持正则表达式的匹配和处理。使用re模块可以进行正则表达式的编译、匹配、替换等操作,常用的函数包括:
函数 | 描述 |
---|---|
re.compile(pattern, flags) | 编译正则表达式并返回一个正则表达式对象 |
re.match(pattern, string, flags) | 从字符串的开头开始匹配正则表达式,如果匹配成功,则返回一个匹配对象;否则返回None |
re.search(pattern, string, flags) | 在字符串中搜索正则表达式的第一个匹配项,如果匹配成功,则返回一个匹配对象;否则返回None |
re.findall(pattern, string, flags) | 在字符串中搜索正则表达式的所有匹配项,并以列表的形式返回 |
re.sub(pattern, repl, string, count=0, flags=0) | 在字符串中搜索正则表达式的所有匹配项,并将其替换为指定的字符串 |
re.split(pattern, string, maxsplit=0, flags=0) | 使用正则表达式对字符串进行分割,并以列表的形式返回分割后的结果 |
- pattern表示正则表达式的模式
- string表示待匹配的字符串
- repl表示替换字符串
- flags表示正则表达式的匹配模式
- count表示替换的次数
- maxsplit表示分割的次数。
- 使用re模块时,需要注意flags参数,它可以指定正则表达式的匹配模式。常用的匹配模式包括:
匹配模式 | 描述 |
---|---|
re.I | 忽略大小写 |
re.M | 多行匹配 |
re.S | 让.匹配包括换行符在内的所有字符 |
re.U | Unicode匹配模式 |
re.X | 忽略正则表达式中的空格和注释 |
匹配单个字符栗子
python
import re
# . 匹配任意1个字符(除了\n)
# 匹配数据
result = re.match("yuanyouyishi.", "yuanyouyishi\n")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到")
# [ ] 匹配[ ]中列举的字符
# 匹配数据
result = re.match("yuanyouyishi[123abc]", "yuanyouyishi-")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到")
# \d 匹配数字,即0-9 => [0123456789] => [0-9]
# 匹配数据
result = re.match("yuanyouyishi\d", "yuanyouyishi5")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到")
# \D 匹配非数字,即不是数字
# 匹配数据
result = re.match("yuanyouyishi\D", "yuanyouyishi-")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到")
# \s 匹配空白,即空格,tab键
# 匹配数据
result = re.match("yuanyouyishi\s111", "yuanyouyishi\t111")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到")
# \S 匹配非空白
# 匹配数据
result = re.match("yuanyouyishi\S", "yuanyouyishi\t")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到")
# \w 匹配非特殊字符,即a-z, A-Z, 0-9, _, 汉字
# 匹配数据
result = re.match("yuanyouyishi\w", "yuanyouyishi!")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到")
# \W 匹配特殊字符,即非字母, 非数字, 非_, 非汉字
# 匹配数据
result = re.match("yuanyouyishi\W", "yuanyouyishi0")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到")
匹配多个字符栗子
python
import re
# * 匹配前一个字符出现0次或者无限次,即可有可无
# 匹配数据
result = re.match("yuanyouyishi\d*yuanyouyishi", "yuanyouyishiyuanyouyishi")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到")
# + 匹配前一个字符出现1次或者无限次,即至少有1次
# 匹配数据
result = re.match("yuanyouyishi\d+yuanyouyishi", "yuanyouyishi12yuanyouyishi")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到")
# ? 匹配前一个字符出现1次或者0次,即要么有1次,要么没有
result = re.match("yuanyouyishi\d?yuanyouyishi", "yuanyouyishiyuanyouyishi")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到")
# {m} 匹配前一个字符出现m次
result = re.match("yuanyouyishi\d{2}yuanyouyishi", "yuanyouyishi12yuanyouyishi")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到")
# {m,n} 匹配前一个字符出现从m到n次
result = re.match("yuanyouyishi\d{2,5}yuanyouyishi", "yuanyouyishi12112312312312312yuanyouyishi")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到")
匹配开头和结尾栗子
python
import re
# ^ 匹配字符串开头
# 匹配数据
result = re.match("^\dyuanyouyishi", "22yuanyouyishi")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到")
# 以数字为开头的字符串
result = re.match("^\d.*", "2yuanyouyishi")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到")
# $ 匹配字符串结尾
result = re.match(".*\d$", "yuanyouyishi")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到")
# 匹配以数字为开头以数字为结尾
result = re.match("^\d.*\d$", "11yuanyouyishi22")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到")
# [^指定字符] 匹配除了指定字符以外的所有字符
result = re.match("^\d.*[^4]$", "11yuanyouyishi@")
# 获取数据
if result:
info = result.group()
print(info)
else:
print("没有匹配到")
匹配分组栗子
python
import re
# 1需求:在列表中["apple", "banana", "orange", "pear"],匹配apple和pear
fruit = ["apple", "banana", "orange", "pear"]
# 获取字符串数据
# | 匹配左右任意一个表达式
for value in fruit:
result = re.match("apple|pear", value)
# 判断匹配是否成功
if result:
info = result.group()
print("我想吃的水果:",value)
else:
print("这个不是我想吃的水果")
# 2需求:匹配出163、126、qq等邮箱
# | 匹配左右任意一个表达式
# (ab) 将括号中字符作为一个分组
# \ 转义字符
result = re.match("[a-zA-Z0-9_]{4,20}@(163|126|qq)\.com", "hello@qq.com")
info = result.group()
print(info)
# 3需求:匹配qq:10567这样的数据,提取出来qq文字和qq号码
# group(0)代表的是匹配的所有数据 1:第一个分组的数据 2:第二个分组的数据 顺序是从左到右依次排序的
result = re.match("(qq):([1-9]\d{4,11})", "qq:10567")
if result:
info = result.group(0)
print(info)
num = result.group(2)
print(num)
type = result.group(1)
print(type)
else:
print("匹配失败")
# 4需求:匹配出<html>hh</html>
# \num 引用分组num匹配到的字符串
result = re.match("<([a-zA-Z1-6]{4})>.*</\\1>", "<html>hh</html>")
if result:
info = result.group()
print(info)
else:
print("匹配失败")
# 5需求:匹配出<html><h1>www.yuanyou.cn</h1></html>
result = re.match("<([a-zA-Z1-6]{4})><([a-zA-Z1-6]{2})>.*</\\2></\\1>", "<html><h1>www.yuanyou.cn</h1></html>")
if result:
info = result.group()
print(info)
else:
print("匹配失败")
# 6需求:匹配出<html><h1>www.yuanyou.cn</h1></html>
# (?P<name>) 分组起别名
# (?P=name) 引用别名为name分组匹配到的字符串
result = re.match("<(?P<html>[a-zA-Z1-6]{4})><(?P<h1>[a-zA-Z1-6]{2})>.*</(?P=h1)></(?P=html)>", "<html><h1>www.yuanyou.cn</h1></html>")
if result:
info = result.group()
print(info)
else:
print("匹配失败")