多线程特点_随机性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import threading


# 使用多线程来模拟小明一边编写num行代码,一边听count首音乐功能实现。
def coding(name, num):
for i in range(num):
print(f"{name}正在敲{i}行代码")


def music(name, count):
for i in range(count):
print(f"{name}正在听{i}遍音乐")


# args 元组
# kwargs 字典
if __name__ == '__main__':
t1 = threading.Thread(target=coding, args=("小明", 100))
t2 = threading.Thread(target=music, args=("小红", 100))
t1.start()
t2.start()

多线程特点_守护线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#
# 假如创建一个子线程,这个子线程执行完大概需要2.5秒钟,
# 现在让主线程执行1秒钟就退出程序,查看一下执行结果
import time, threading
def work():
for i in range(20):
time.sleep(0.25)
print(f"{i}次工作中")
if __name__ == '__main__':
# 方式一:创建子线程的时候指定守护线程daemon=True
# t1 = threading.Thread(target=work,daemon=True)
t1 = threading.Thread(target=work, daemon=True)
t1.setDaemon(True)
t1.start()
time.sleep(1)
print("主线程结束了!!!")

多线程特点_数据共享

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 定义一个列表类型的全局变量,创建两个子线程分别执行
# 向全局变量添加数据的任务和向全局变量读取数据的任务,
# 查看线程之间是否共享全局变量数据
import threading
import time
my_list = []
# 添加数据
def write_data():
for i in range(10):
time.sleep(0.5)
my_list.append(i)
print("写入数据", i)
print(f"调用write_data{my_list}")
# 读取数据
def read_data():
time.sleep(1)
print(f"调用read_data{my_list}")
if __name__ == '__main__':
t1 = threading.Thread(target=write_data)
t2 = threading.Thread(target=read_data)
t1.start()
t2.start()

多线程特点_互斥锁

  • 图解

    1742990301370

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    import threading

    global_num = 0
    # 创建了一个锁
    lk = threading.Lock()
    def fun1():
    #加锁
    lk.acquire()
    global global_num
    for i in range(10000000):
    global_num += 1
    print(f"fun1的函数结果{global_num}")
    #释放锁
    # lk.release()
    def fun2():
    # 加锁
    lk.acquire()
    global global_num
    for i in range(10000000):
    global_num += 1
    print(f"fun2的函数结果{global_num}")
    lk.release()
    # 释放锁
    if __name__ == '__main__':
    t1 = threading.Thread(target=fun1)
    t2 = threading.Thread(target=fun2)
    t2.start()
    t1.start()


进程和线程对比

1
2
3
4
进程和线程的区别:
1. 线程依赖进程, 进程是CPU分配资源的基本单位, 线程是CPU调度资源的基本单位.
2. 进程更消耗资源, 不能共享全局变量, 相对更稳定.
3. 线程更轻量级, 可以共享全局变量, 相对更灵活.

迭代器入门

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
"""
迭代器介绍
概述:
自定义迭代器,只要重写 __iter__() 和__next()__方法,就可以称之为迭代器
目的:
隐藏底层的逻辑,让用户使用方便
惰性加载,用的时候用才会获取
回顾:
for i in 可迭代类型
"""
# 需求 : 模拟range(1,6) ,自定义迭代器
# for i in range(6, 1):
# print(i)


# 场景2:自定义迭代器
class my_class:
# range(1, 6): 参考别人的迭代器 。起始 结束
def __init__(self, start, end):
self.current_value = start
self.end = end

# # 返回当前对象(即:迭代器对象)
def __iter__(self):
return self

# 返回当前值,并更新当前值
def __next__(self):
# 判断当前值不合法
if self.current_value >= self.end:
raise StopIteration # 抛出异常,迭代结束
# 走到这里,说明当前值合法。返回当前值,并且更新当前值
value = self.current_value
self.current_value += 1
return value
# self.current_value+=1
# return self.current_value-1
# 使用场景:
for i in my_class(1, 6):

print(i)

生成器介绍

  • 案例1: 推导式写法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    def my_fun():
    for i in range(1, 11):
    # my_list =[] #创建
    # for i in range(1,11):
    # my_list.append(i) #添加
    # return my_list #返回

    #等价于
    # yield 在这里做了三件事
    # 1:创建生成器对象
    # 2:把值存储在生成器中
    # 3:返回生成器
    yield i

    #1:创建生成器对象
    my_g1 = my_fun()
    print(type(my_g1))#<class 'generator'>
    print(next(my_g1))
    print(next(my_g1))
    print("*"*24)
    for i in my_g1:
    print(i)
    print("*")
  • 案例2: yield关键字

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    """
    案例: 演示生成器之 推导式写法.

    生成器介绍:
    概述:
    所谓的生成器就是基于 数据规则, 用一部分在生成一部分, 而不是一下子生成完所有.
    目的:
    可以节省大量的内存.
    实现方式:
    1. 推导式写法.
    2. yield关键字
    """

    # 需求: 通过yield方式, 获取到生成器之 1 ~ 10之间的整数.
    # 回顾: 推导式写法.
    my_g = (i for i in range(1, 11))

    # yield方式如下.
    # 1.定义函数, 存储到生成器中, 并返回.
    def my_fun():
    # my_list = [] # 创建
    # for i in range(1, 11):
    # my_list.append(i) # 添加
    # return my_list # 返回

    # 效果类似于上边的代码.
    # yield在这里做了三件事儿: 1.创建生成器对象. 2.把值存储到生成器中. 3.返回生成器.
    for i in range(1, 11):
    yield i

    # 2.测试.
    my_g2 = my_fun()
    print(type(my_g2)) # <class 'generator'>

    print(next(my_g2))
    print(next(my_g2))
    print('-' * 23)
    for i in my_g2:
    print(i)
  • 案例3: 批量歌词

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    """
    需求:基于传入的文件,创建生成器 ,生产批次歌词
    分批加载数据: 歌词 假设 8条为一个批次
    """
    import math
    # 定义函数 返回生成器
    # batch_size 批次大小
    def dataset_loader(batch_size):
    # 读取文件
    with open("./data/jaychou_lyrics.txt", "r", encoding="utf-8") as src_f:
    # 一次读取一行数据
    lines = src_f.readlines()
    # 计算批次总数 ,假设 5批 每个批次8条 5*8 = 40条数据
    # 之所以使用math.ceil,是因为考虑到可能最后歌词数不够8条,也算一个批次
    # 总批次(total_batch) =celi(len(lines) /batch_size)
    total_batch = math.ceil(len(lines) / batch_size)

    # 循环 获取到【每个批次】的数据,放入生成器中,并返回
    for idx in range(total_batch):
    # 如何按照我们的要求来取批次
    # 假设total_batch 是5个批次 range(5) 则idx值 0 1 2 3 4
    # 第一批歌词,批次索引(idx=0),歌词为:第1条~第8条 索引为0~7
    # 第二批格式,批次索引(idx=1),歌词为:第9条~第16条 索引8~15
    # 第三批格式,批次索引(idx=2),歌词为:第17条~24条 索引:16~23
    # yield lines[0:8] 包左不包右 前面的值 idx * batch_size
    # yield lines[8:16] 包左不包右 前面的值 idx *batch_size
    yield lines[idx * batch_size:idx * batch_size + batch_size]
    d1=dataset_loader(8)
    # print(next(d1))

    for tmp_batch in d1:
    print(tmp_batch)

Property属性介绍

  • 场景1: 装饰器用法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    """
    property属性介绍:
    概述/目的/作用:
    把函数当做变量来使用
    实现方式:
    方式一:装饰器
    方式二:类属性
    实现方式一:
    property的装饰器用法
    @property 修饰 获取值的函数 get_age
    @获取值的函数名.setter 修饰 设置值的函数 set_age
    """
    # 没有property属性
    class student:
    # 私有化属性 age
    def __init__(self):
    self.__age = 18
    # 没有property属性的时候:
    # 提供公共的访问接口 (get/set)
    @property
    def age(self):
    return self.__age

    @age.setter
    def age(self, age):
    self.__age = age
    if __name__ == '__main__':
    s1 = student()
    # print(s1.get_age())
    # print(s1.get_age)
    print(s1.age)
    s1.age=20
    print(s1.age)
  • 场景2: 类属性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    """
    property属性介绍:
    概述/目的/作用:
    把函数当做变量来使用
    实现方式:
    方式一:装饰器
    方式二:类属性
    实现方式一:
    property的装饰器用法
    @property 修饰 获取值的函数 get_age
    @获取值的函数名.setter 修饰 设置值的函数 set_age
    """


    # 没有property属性
    class student:
    # 私有化属性 age
    def __init__(self):
    self.__age = 18

    # 没有property属性的时候:
    # 提供公共的访问接口 (get/set)

    def get_age(self):
    return self.__age

    def set_age(self, age):
    self.__age = age

    age = property(get_age, set_age)


    if __name__ == '__main__':
    s1 = student()
    # print(s1.get_age())
    # print(s1.get_age)
    print(s1.age)
    s1.age = 20
    print(s1.age)

正则表达式入门

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
"""

re使用方法:
1:导包
import re
2:正则匹配
result=re.match('正则表达式',‘要校验的字符串’) 从前向后依次匹配。只要能匹配上即可
result=re.search('正则表达式',‘要校验的字符串’) 分段查找
3:获取匹配结果
result.group()
细节:
1:学正则表达式,就是学习正则表达式的规则,你不用背。网上一大堆
2:关于正则对大家的要求是,能用我们讲的规则,看懂别人的表达式,且会简单的修改即可
3:正则不独属于python像sql、java、php、go 等都支持
"""
import re
# . 匹配任意1个字符
#参数一 匹配规则
# 参数二 要匹配字符串
# result = re.match('.it','ait') #匹配成功
# result = re.match('.it','你it') #匹配成功、
# result = re.match('.it','你好it') #匹配失败
# result = re.match('.it','@it') #匹配成功

# [] 匹配[]中列举的字符
# result = re.match('[abc]it','ait')
# result = re.match('[abc]it','hit')
# result = re.match('[abc]it','a it') #匹配失败

# [^] 匹配[]中列举的字符
# result = re.match('[^abc]it','ait') #匹配失败
# result = re.match('[^abc]it','a it')匹配失败

#[3-7] 从3个开始到7
# result = re.match('[3-7]it','7it')
# result = re.match('[a-zA-Z0-9]it','_it')

#\d 匹配数字0-9
# result = re.match('a\\dit','a-8it') #a8it

#\D 即匹配的不是数字
# result = re.match('a\\Dit','a-it')

# \s 匹配空白 即空格 tab键
# result = re.match('a\sit','a it')
# result = re.match('a\sit','a it')#匹配失败
# result = re.match('a\sit','a\tit') #匹配成功

# \S 匹配非空白
# result = re.match('a\Sit','a_it') #匹配成功

# \w
# result = re.match('a[\w]it','a_it')

# result = re.match('a[\W]it','a!it')
# result = re.match('a[\W]it','a*it')


# result = re.match("itcast.", "itcast2fdafdafdas")
result = re.match("a[^abc]it","a it")
if result:
print(result.group())
else:
print("匹配失败")




正则表达式_校验单个字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
"""
案例: 演示正则表达式之 校验单个字符.

正则表达式介绍:
概述:
正确的, 符合特定规则的 字符串.
Regular Expression, 正则表达式, 简称: re
细节:
1. 学正则表达式, 就是学正则表达式的规则, 你用不背, 网上一搜一大堆.
2. 关于正则我对大家的要求是, 能用我们讲的规则, 看懂别人写的式子, 且会简单修改即可.
3. 正则不独属于Python, 像Java, JavaScript, PHP, Go等都支持.
步骤:
1. 导包
import re
2. 正则匹配
result = re.match('正则表达式', '要校验的字符串') 从前往后依次匹配,只要能匹配即可.
result = re.search('正则表达式', '要校验的字符串') 分段查找.
3. 获取匹配结果.
result.group()
正则常用的规则:
. 代表任意的 1个字符, 除了 \n
\. 取消.的特殊含义, 就是1个普通的.
a 代表1个普通的字符 a
[abc] 代表a,b,c中任意的1个字符
[^abc] 代表除了a,b,c外, 任意的1个字符
\d 代表数字, 等价于 [0-9]
\D 代表非数字, 等价于 [^0-9]
\s 代表空白字符, 等价于 [\t\n\r]
\S 代表非空白字符
\w 代表非特殊字符, 即: 数字, 字母, 下划线, 汉字, [a-zA-Z0-9_汉字]
\W 代表特殊字符, 非字母,数字,下划线,汉字

^
$

*
?
+
{n}
{n,}
{n,m}

| 代表 或者的意思
()
\num

扩展:
(?P<分组名>)
(?P=分组名)
"""

# 需求: 正则入门.

# 1.导包
import re

# 2.正则校验, 参1: 正则规则, 参2: 要被校验的字符串
# result = re.match('.it', 'ait') # 匹配成功
# result = re.match('.it', '你it') # 匹配成功
# result = re.match('.it', '你好it') # 失败

# result = re.match('\.it', '你it') # 失败
# result = re.match('\.it', '.it') # 匹配成功

result = re.match('[ahg]it', 'ait') # 匹配成功
result = re.match('[ahg]it', 'hit') # 匹配成功
result = re.match('[ahg]it', 'git') # 匹配成功
result = re.match('[ahg]it', 'g it') # 失败


result = re.match('[^ahg]it', 'ait') # 失败
result = re.match('[^ahg]it', 'x it') # 失败
result = re.match('[^ahg]it', 'xit') # 匹配成功
result = re.match('[^ahg]it', 'xitabcxyz') # 匹配成功, 从前往后匹配, 匹配到就返回.
result = re.match('[^ahg]it', 'abcxitabcxyz') # 失败, 从前往后依次查找.
# result = re.search('[^ahg]it', 'abcxitabcxyz') # 失败, 从前往后依次查找.


result = re.match('[3-7]it', '3it') # 匹配成功
result = re.match('[3-7]it', '-it') # 失败, [3-7]等价于[34567]


result = re.match('a\\dhm', 'a1hm') # 匹配成功
result = re.match('a\\dhm', 'a10hm') # 失败

result = re.match('a\\Dhm', 'a!hm') # 匹配成功
result = re.match('a\\Dhm', 'abhm') # 匹配成功


result = re.match('a\\shm', 'abhm') # 失败
result = re.match('a\\shm', 'a\thm') # 匹配成功
result = re.match('a\\shm', 'a\nhm') # 匹配成功
result = re.match('a\\shm', 'a hm') # 匹配成功

result = re.match('a\\whm', 'a\thm') # 失败
result = re.match('a\\whm', 'a!hm') # 失败
result = re.match('a\\whm', 'axhm') # 匹配成功
result = re.match('a\\whm', 'a_hm') # 匹配成功
result = re.match('a\\whm', 'a6hm') # 匹配成功
result = re.match('a\\whm', 'aYhm') # 匹配成功
result = re.match('a\\whm', 'a夯hm') # 匹配成功

# 3.获取匹配结果.
if result:
print(result.group())
else:
print('匹配失败')

正则表达式_校验多个字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import re

# *匹配前一个字符出现0次或者无限次,即可有可无
# result = re.match("hm.*","abchm123")


# + 匹配前一个字符出现1次或者无限次
# result = re.match(".+hm.*","abchm")
result = re.match(".+hm.*", "hm123")

# ? 匹配前一个字符出现1次或者0次
# result = re.match(".?hm.*","abchm123")
# result = re.match(".?hm.*","ahm123")

# {m} 匹配前一个字符出现m次
# result = re.match("\d{3}hm\w{2,5}","123hm123")
result = re.match("\d{3}hm\w{2,5}", "1234hm123") # 匹配失败
result = re.match("\d{3,}hm\w{2,5}", "123hmabc")

if result:
print(result.group())
else:
print("匹配失败")
import re

# *匹配前一个字符出现0次或者无限次,即可有可无
# result = re.match("hm.*","abchm123")


# + 匹配前一个字符出现1次或者无限次
# result = re.match(".+hm.*","abchm")
result = re.match(".+hm.*", "hm123")

# ? 匹配前一个字符出现1次或者0次
# result = re.match(".?hm.*","abchm123")
# result = re.match(".?hm.*","ahm123")

# {m} 匹配前一个字符出现m次
# result = re.match("\d{3}hm\w{2,5}","123hm123")
result = re.match("\d{3}hm\w{2,5}", "1234hm123") # 匹配失败
result = re.match("\d{3,}hm\w{2,5}", "123hmabc")

if result:
print(result.group())
else:
print("匹配失败")

正则表达式_校验开头和结尾

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import re
# result = re.match("^\d+.", "qabc123xyz") #失败
# result = re.match("\d+.", "123xyz")

# result = re.match("^\d+.*[a-zA-Z]{3}", "abc123xyz12")
# result = re.match("^\d+.*[a-zA-Z]{3}", "123你好xyz12")

# result = re.match("^\d+.*[a-zA-Z]{3}$", "123你好abc12")

# result = re.match("^\d+.*[a-zA-Z]{3}$", "123你好abc12a&c")
# if result:
# print(result.group())
# else:
# print("匹配失败")


# 校验手机号
# 规则1: 长度必须是11位
# 规则2:第1位必须是1
# 规则3:必须都是纯数字
# 规则4: 第二位数字 3-9

result = re.match("^1[3-9]\d{9}$", "13345678921111")
if result:
print(result.group())
else:
print("匹配失败")

正则表达式_校验分组

1
2
3
4
5
6
7
8
9
# 1 需求:在列表中["apple", "banana", "orange", "pear"],匹配apple和pearfruit = ["apple", "banana", "orange", "pear"]
#
import re
f = ["apple", "banana", "orange", "pear"]
for f_tmp in f:
if re.match('apple|pear',f_tmp):
print(f"喜欢吃{f_tmp}")
else:
print(f"不喜欢吃{f_tmp}")

正则表达式_校验邮箱

1
2
3
4
5
6
7
8
9
10
 # 2 需求:匹配出163、126、qq等邮箱
email ="axcdsa@163.com"
#校验邮箱合法
result = re.match("^[a-zA-Z_0-9]{6,18}@(163|126|qq)\.com$", email)
if result:
print(result.group())
print(result.group(0))#获取第0组信息,效果同上,即;整个匹配到的结果。整个匹配到的结果是0组
print(result.group(1)) #从左往右数,第几个左小括号,就表示第几组
else:
print("匹配失败")

正则表达式_提取QQ号

1
2
3
4
5
6
7
8
9
10
11
12
13
#需求是匹配QQ号
# 数字 qq:10567
import re
result = re.match("^(qq):([1-9]\d{4,10})$", "qq:10567")
if result:
print(result.group())
print(result.group(0))
print(result.group(1))
print(result.group(2))
else:
print("匹配失败")


正则表达式_校验html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
"""
正则校验:
| 代表 或的意思
() 代表分组 ,从左向右数, 第几个左小括号(,就表示第几组
\num 代表引用第几组的内容

拓展:
(?P<分组名>) 设置分组
(?P=分组名) 使用分组

"""
# 需求一:匹配出 <html>hh</html>

import re
# html_s='<html>hh</html>'
# # result = re.match("<[a-zA-Z]{1,4}>.*</[a-zA-Z]{1,4}>", html_s)
#
# result = re.match(r"<([a-zA-Z]{1,4})>.*</\1>", html_s)
# result = re.match("<([a-zA-Z]{1,4})>.*</\\1>", html_s)
# #引入分组的概念
# if result:
# print(result.group())
# else:
# print("匹配失败")



html_s='<html><h1>我是html界面</h1></html>'

# result = re.match("<[a-zA-Z]{1,4}><h[1-6]>.*</h[1-6]></[a-zA-Z]{1,4}>", html_s)

#演示分组
# result = re.match(r"<([a-zA-Z]{1,4})><(h[1-6])>.*</\2></\1>", html_s)


result = re.match("<(?P<A>[a-zA-Z]{1,4})><(?P<B>h[1-6])>.*</(?P=B)></(?P=A)>", html_s)

#引入分组的概念
if result:
print(result.group())
else:
print("匹配失败")