一、property属性
1.作用:把方法的调用变成属性调用
class Person():
    def __init__(self):
        self.__age = 0
    @property
    def age(self):
        return self.__age
    @age.setter
    def age(self,age):
        self.__age = age
p = Person()
p.age = 10
print(p.age)
2.类属性方式
class Person():
    def __init__(self):
        self.__age = 0
    def get_age(self):
        print('这里获取了age')
        return self.__age
    def set_age(self,age):
        print('这里设置了age')
        self.__age = age
    # 属性中第一个是get方法 第二个是set方法
    age = property(get_age, set_age)
p = Person()
p.age = 10
print(p.age)
二、with和上下文管理器
1. 使用方式
with open(文件名,模式) as f:
	文件读写
2. 作用
文件打开后出现异常没有关闭,或数据库没有关闭,会导致资源浪费,内存泄漏
3. 上下文管理器
- 只要重写了__enter__和__exit__方法,就是上下文管理器;
 - as之后的变量是上下文管理器__enter__返回的对象!
 - 不管有没有出现异常,下文__exit__都会在with语句执行后自动执行
 
class File():
    def __init__(self, path, model):
        self.path = path
        self.model = model
    def __enter__(self):
        print('--这里是上文--')
        self.file = open(self.path, self.model)
        return self.file
    def __exit__(self, exc_type, exc_val, exc_tb):
        print('--这里是下文--')
        self.file.close()
with File('./1.txt', 'w') as f:
    f.write('aaaa')
    1/0
    print('--写数据!!!---')
print('程序执行结束')
三. 生成器
1. 生成器推导式
通过普通方式创建容器,容器内存就是所有元素内存 生成器可以不必创建完整的list,从而节省大量的空间
d = (ele for ele in range(100))
# 1. 使用next迭代
res1 = next(d)
print(res1)
res2 = next(d)
print(res2)
# 2. 使用for循环迭代
for ele in d:
	print(ele)
2. yield关键字
yield会保存函数执行状态,并返回当前生成数值
def generater(num):
	for i in range(num):
		print('---start---')
		yield i
		print('---end---')
g = generater(5)
# 1. 使用next迭代
next(g)
# 2. 使用for循环迭代
for ele in g:
	print(ele)
四、浅拷贝和深拷贝
拷贝仅限于可变类型(列表、字典、集合)!!!!
对于不可变类型,都是直接引用(与赋值操作相同),不开辟新空间
如果是不可变类型中嵌套可变类型,一律当作可变类型处理(例如:(1,2,[2,3,4]))
1.浅拷贝
浅拷贝:只拷贝第一层数据
列表的切片其实是浅拷贝(例如: list[:]是对list列表的浅拷贝)

# 浅拷贝:只拷贝第一层数据
import copy
a = [1,2]
b = [4,5,6]
c = [a,b]
d = copy.copy(c)
print(id(c))
print(id(d))
print(id(c[0]))
print(id(d[0]))
2. 深拷贝
可变类型嵌套了可变类型,对每一层可变对象都会拷贝
# 深拷贝:每一层都拷贝
import copy
a = [1,2]
b = [4,5,6]
c = [a,b]
d = copy.deepcopy(c)
print(id(c))
print(id(d))
print(id(c[0]))
print(id(d[0]))


四、正则表达式
1. 定义
对字符串的匹配规则
2. 单个字符匹配规则

import re
# result = re.match('我今年\d岁, 名字叫\w', '我今年7岁, 名字叫啦')
result = re.match(r'我今年[0-9]岁, 名字叫\w', '我今年7岁, 名字叫啦')
if result:
    print(result.group())
else:
    print('没有匹配!')
注意:
- 匹配规则前面加上r,表示原生字符串,告诉解释器不要用使用转义字符
 - 补充:\b 单次边界 \B 非单词边界
 
3. 多个字符匹配规则

import re
result = re.match(r'[a-zA-Z][a-zA-Z0-9]{2,9}@qq\.com', 'aafd123123@qq.com')
if result:
    print(result.group())
else:
    print('没有匹配!')
4. 匹配开头和结尾

5. 匹配分组

6. 补充
- 
    
如何返回第一次匹配字符串的下标
import re stra = 'bread is good good' p = re.compile('good') result1 = p.search(stra).span() # 返回值是元组 print(result1) - 
    
使用正则提取出字符串中的单词
import re s="i love you not because of who 234 you are, 234 but 3234ser because of who i am when i am with you" content=re.findall(r"\b[a-zA-Z]+\b",s) print(content) - 
    
使用正则表达式匹配合法的邮件地址:
import re s="xiasd@163.com, sdlfkj@.com sdflkj@180.com solodfdsf@123.com sdlfjxiaori@139.com saldkfj.com oisdfo@.sodf.com.com" content=re.findall(r"\w+@\w+.com",s) print(content) - 
    
提取每行中完整的年月日和时间字段
s="se234 1987-02-09 07:30:00 1987-02-10 07:25:00" content= re.findall(r"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}",s ,re.M) print(s) print(content)