Python高级语法(二)

property、with、深/浅拷贝、正则

Posted by 新宇 on January 12, 2020

一、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. 补充

  1. 如何返回第一次匹配字符串的下标

     import re
     stra = 'bread is good good'
     p = re.compile('good')
     result1 = p.search(stra).span()
     # 返回值是元组
    
     print(result1)
    
    
  2. 使用正则提取出字符串中的单词

     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)
    
  3. 使用正则表达式匹配合法的邮件地址:

     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)
    
  4. 提取每行中完整的年月日和时间字段

     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)