Django–闭包-装饰器-正则表达式

「这是我参与11月更文挑战的第25天,活动详情查看:2021最后一次更文挑战」。

1.property属性

概念:property属性就是负责把一个方法当做属性进行使用,这样做可以简化代码使用。

定义property属性有两种方式:

  • 装饰器方式;
  • 类属性方式。

1.1 装饰器方式

class Person(object):

    def __init__(self):
        self.__age = 0

    # 装饰器方式的property,把age方法当做属性使用,表示当获取属性时会执行下面修饰的方法
    @property
    def age(self):
        return self.__age

    # 把age方法当做属性用,表示当设置属性时会执行下面修饰的方法
    @age.setter
    def age(self, new_age):
        if new_age >= 150:
            print("成精了")
        else:
            self.__age = new_age

p = Person()
print(p.age)
p.age = 100
print(p.age)
p.age = 1000
复制代码

说明:

  • @property:表示把方法当做属性使用,表示当获取属性时会执行下面修饰的方法;
  • @方法名.setter:表示把方法当做属性使用,表示当设置属性时会执行下面修饰的方法;
  • 装饰器方式的property属性修饰的方法名一定要一样。

1.2 类属性方式

class Person(object):
    def __init__(self):
        self.__age = 0

    def get_age(self):
        """当获取age属性的时候会执行该方法"""
        return self.__age

    def set_age(self, new_age):
        """当设置age属性的时候会执行该方法"""
        if new_age >= 150:
            print("成精了")
        else:
            self.__age = new_age

    # 类属性方式的property属性
    age = property(get_age, set_age)

p = Person()
print(p.age)
p.age = 100
print(p.age)
p.age = 1000
复制代码

property的参数说明:

  • 第一个参数是获取属性时要执行的方法;
  • 第二个参数是设置属性时要执行的方法。

2.with语句和上下文管理器

with open("xxx.txt", "w") as f:
    f.write("hello python")
复制代码

这样写就会让文件在执行完毕后自动关闭,避免错误。

2.1 上下文管理器

一个类只要实现了__enter__()和__exit__() 这两个方法,通过该类创建的对象我们就称之为上下文管理器。

上下文管理器可以使用with语句,with语句的后面就是上下文管理器做支撑的:

class File(object):

    # 初始化方法
    def __init__(self, file_name, file_model):
        # 定义变量保存文件名和打开模式
        self.file_name = file_name
        self.file_model = file_model

    # 上下文方法
    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()

if __name__ == '__main__':
    with File("1.txt", "r") as file:
        file_data = file.read()
        print(file_data)
复制代码

说明:

  • __enter__()表示上下文方法,需要返回一个操作对象;
  • __exit__()表示下文方法,with语句执行完成会自动执行,即使出现异常也会执行该方法。

2.2 上下文管理器的另外一种实现方法

假如想要让一个函数称为上下文管理器,Python还提供了一个@contextmanager的装饰器,更进一步简化了上下文管理器的实现方式。

通过yield将函数分割成两部分,yield上面的语句在__enter__()方法中执行,yield下面的语句在__exit__()方法中执行,紧跟在yield后面的参数是函数的返回值:

# 导入装饰器from contextlib import contextmanager

# 装饰器装饰函数,让其称为一个上下文管理器对象
@contextmanagerdef my_open(path, mode):
    try:
        # 打开文件
        file = open(file_name, file_mode)
        # yield之前的代码好比是上文方法
        yield file
    except Exception as e:
        print(e)
    finally:
        print("over")
        # yield下面的代码好比是下文方法
        file.close()

# 使用with语句with my_open('out.txt', 'w') as f:
    f.write("hello , the simplest context manager")
复制代码

3.生成器的创建方式

概念:根据程序员制定的规则循环生成数据, 当条件不成立时则生成数据结束。数据不是一次性全部生成处理,而是使用一个,再生成一个,可以节约大量的内存

创建生成器的方式:

  • 生成器推导式;
  • yield关键字。

3.1 生成器推导式

与列表推导式类似,只不过生成器推导式使用小括号:

"""生成器推导式"""
my_generator = (i*2 for i in range(5))
print(my_generator)

for value in my_generator:
    print(value)

# next获取生成器下一个值
# value = next(my_generator)
# print(value)
复制代码

next函数获取生成器中的下一个值。

3.2 yield关键字

只要在def函数中看到yield关键字,那么就是生成器:

def my_generator(n):
    for i in range(n):
        print('开始生成')
        yield i
        print('完成一次')

if __name__ == '__main__':
    g = my_generator(2)
    for i in g:
        print(i)
复制代码

代码说明:

  • 代码执行到yield会暂停,然后把结果返回出去,下次启动器会在暂停的位置继续往下执行;
  • 生成器如果把数据生成完成,再次获取生成器中的下一个数据会抛出一个StopIteration异常,表示停止迭代异常;
  • while循环内部没有处理异常操作,需要手动添加处理异常操作;
  • for循环内部自动处理了停止迭代异常,推荐使用。

4.深拷贝和浅拷贝

浅拷贝:copy函数是浅拷贝,只对可变类型的第一层对象进行拷贝,对拷贝的对象开辟新的内存空间进行存储,不会拷贝对象内部的子对象。

  • 不可变类型进行浅拷贝不会给拷贝的对象开辟新的内存空间,而只是拷贝了这个对象的引用;
  • 可变类型进行浅拷贝只对可变类型的第一层对象进行拷贝,对拷贝的对象会开辟新的内存空间进行存储,子对象不进行拷贝。

深拷贝:deepcopy函数是深拷贝,只要发现对象有可变类型就会对该对象到最后一个可变类型的每一层对象进行拷贝,对每一层拷贝的对象都会开辟新的内存空间进行存储。

  • 不可变类型进行深拷贝,如果子对象没有可变类型则不会进行拷贝,而只是拷贝了这个对象的引用,否则会对该对象到最后一个可变类型的每一层对象进行拷贝,对每一层拷贝的对象都会开辟新的内存空间进行存储。

5.正则表达式

实际应用:匹配符合某些复杂规则的字符串

概念:正则表达式就是记录文本规则的代码(0\d{2}-\d{8} 这就是一个正则表达式,表达的意思是匹配的是座机号码)

5.1 re模块

在python中需要通过正则表达式匹配对字符串进行匹配的时候,需要导入re模块:

# 导入re模块import re

# 使用match方法进行匹配操作
result = re.match(正则表达式,要匹配的字符串)

# 如果上一步匹配到数据的话,可以使用group方法来提取数据
result.group()
复制代码

re模块的使用:

import re

# 使用match方法进行匹配操作
result = re.match("itcast","itcast.cn")
# 获取匹配结果
info = result.group()
print(info)
复制代码
  • re.match()根据正则表达式从头开始匹配字符串数据;
  • re.search()从头开始找;
  • re.findall()查找全部;
  • 非贪婪。

5.2 匹配单个字符

代码 功能
. 匹配任意一个字符(除了\n)(re.S,re.DOTALL)
[] []匹配[]中列举的字符
\d 匹配数字,即0-9
\D 匹配非数字,即不是数字
\s 匹配空白,如空格,tab键
\S 匹配非空白
\w 匹配非特殊字符,即a-z,A_Z,_,汉字
\W 匹配特殊字符,非字母、非数字、非汉字

5.3 匹配多个字符

代码 功能
* 匹配前一个字符出现0次或者无数次,即可有可无
+ 匹配前一个字符出现1次或无限次,即至少有1次
匹配前一个字符要么出现1次要么出现0次,即可有可无
{m} 匹配前一个字符出现m次
{m, n} 匹配前一个字符出现从m到n次

5.4 匹配开头和结尾

代码 功能
^ 匹配字符串开头
$ 匹配字符串结尾
[^指定字符] 表示除了指定字符都匹配

5.5 匹配分组

代码 功能
| 匹配左右任意一个表达式
(ab) 将括号中字符作为一个分组
\num 引用分组num匹配到的字符串
(?P) 分组起别名
(?P=name) 引用别名为name分组匹配到的字符串