一、闭包
在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数称为闭包。
优点:
-
无需定义全局变量即可实现通过函数、持续的访问、修改某个值
-
闭包使用的变量的所用于在函数内,难以被错误的调用修改
缺点:
-
由于内部函数持续引用外部函数的值,所以会导致这一部分内存空间不被释放,一直占用内存
#简单闭包
def outer(logo):
def inner(msg):
print(f"<{logo}><msg><logo>")
return inner
fn1=outer("hello")
fn1=("python")
fn1="world"
#<hello><python><hello>
#<hello><world><hello>
#nonlocal关键字:修饰外部函数的变量,内部函数中才可以修改它
def outer(num1):
def inner(num2):
nonlcoal num1
num1+=num2
print(num1)
return inner
fn1=outer(10)
fn1=(10)
fn1=(10)
#20
#30
#案例:ATM存取款
def account_create(initial_amount=0):
def atm(num,deposit=True):
nonlocal initial_amount
if deposit:
initial_amount+=num
print(f"存款{num},账户余额{initial_amount}")
else:
initial_amount-=num
print(f"取款{num},账户余额{initial_amount}")
return atm
atm=account_create()
atm=(100)
atm=(300)
atm=(100,deposit=False)
二、修饰器
装饰器其实也是一种闭包,其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能。
import time
import random
def outer(func):
def inner(): # 定义一个闭包函数
print("我睡觉了")
func() # 执行目标函数
print("我起床了")
return inner
#使用@outer定义在目标函数之上
@outer
def sleep():
print("睡眠中。。。")
time.sleep(random.randint(1,5))
#方式一
# fn=outer(sleep)
# fn()
#方式二
sleep()
三、设计模式
1.单例模式
是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在,并提供一个访问它的全局访问点。
单例的实现模式
#文件一
class StrTools:
pass
#创建对象
str_tool=StrTools()
#文件二
from test import str_tool
s1=str_tool
s2=str_tool
print(s1)
print(s2)
2.工厂模式
将对象的创建由使用原生类本身创建转换到由特定的工厂方法来创建
-
使用工厂类的get_person()方法去创建具体的类对象
-
大批量创建对象的时候有统一的入口,易于代码维护
-
当发生修改,仅修改工厂类的创建方法即可
-
符合现实世界的模式,即由工厂来制作产品(对象)
#父类
class Person:
pass
#子类
class Worker(Person):
pass
class Student(Person):
pass
class Teacher(Person):
pass
class Factory:
def get_person(self,p_type):
if p_type=='w':
return Worker()
elif p_type=='s':
return Student()
else:
return Teacher()
factory=Factory()
wor=factory.get_person('w')
stu=factory.get_person('s')
tea=factory.get_person('t')
四、多线程
进程:就是一个程序,运行在系统之上,那么便称之这个程序为一个运行进程,并分配进程ID方便系统管理。
线程:线程是归属于进程的,一个进程可以开启多个线程,执行不同的工作,是进程的实际工作最小单位。
操作系统中可以运行多个进程,即多任务运行;一个进程内可以运行多个线程,即多线程运行
并行执行
多个进程同时在运行,即不同的程序同时运行——多任务并行执行
一个进程内的多个线程同时在运行——多线程并行执行
import threading
thread_obj=threading.Thread([group[,target[,name[,args[,kwargs]]]]])
-group:暂时无用,未来功能的预留参数
-target:执行的目标任务名
-args:以元组的方式给执行任务传参
-kwargs:以字典方式给执行任务传参
-name:线程名,一般不用设置
#启动线程,让线程开始工作
thread_obj.start()
#多线程
import time
import threading
def sing():
while True:
print("我在唱歌。啦啦啦...")
time.sleep(1)
def dance():
while True:
print("跳舞")
time.sleep(1)
if __name__ == '__main__':
#创建一个唱歌的线程
sing_thread=threading.Thread(target=sing)
#创建一个跳舞的线程
dance_thread=threading.Thread(target=dance)
sing_thread.start()
dance_thread.start()
#传参
import time
import threading
def sing(msg):
while True:
print(msg)
time.sleep(1)
def dance(msg):
while True:
print(msg)
time.sleep(1)
if __name__ == '__main__':
#创建一个唱歌的线程
sing_thread=threading.Thread(target=sing,kwargs={"msg":"我在唱歌啦啦啦"})
#创建一个跳舞的线程
dance_thread=threading.Thread(target=dance,args=("跳舞",))
sing_thread.start()
dance_thread.start()
五、网络编程
Socket负责进程之间的网络数据传输
1.Socket服务端
等待其它进程的连接、可接受发来的消息、可以回复消息
#1.创建Socket对象
import socket
socket_server=socket.socket()
#2.绑定Socekt_server到制定IP和地址
socket_server.bind(host,port)
#3.服务端开始监听端口
socket_server.listen(backlog)
#backlog为int整数,表示允许的连接数量,超出的会等待,可以不填,不填会自动设置一个合理值
#4.接收客户端连接,获得连接对象
conn,address=socket_server.accept()
print(f"接收到客户端连接,连接来自:{address}")
#accept方法是阻塞方法,如果没有连接,会卡在当前这一行不向下执行代码
#accept返回的是一个二元元组,可以使用上述形式,用两个变量接收二元元组的2个元素
#案例
#1.创建Socket对象
import socket
socket_server=socket.socket()
#2.绑定Socekt_server到制定IP和地址
socket_server.bind("localhost",8888)
#3.服务端开始监听端口
socket_server.listen(1)#表示接收连接的数量
# #等地啊客户端连接
# result=socket_server.accept()
# conn=result[0]
# address=result[1]
#4.接收客户端连接,获得连接对象
conn,address=socket_server.accept()
print(f"接收到客户端连接,连接来自:{address}")
while True:
#接收客户端信息
data=conn.recv(1024).decode("UTF-8")
#recv接收的参数是缓冲区大小,一般给1024即可
#recv方法的返回值是一个字节数组也就是bytes对象,不是字符串,可以通过decode方法通过UTF-8编码,将字节数组转换为字符串对象
#发送回复消息
msg=input("请输入你和客户端回复的消息:").encode("UTF-8")#encode可以将字符串编码为字节数组对象
if msg=='exit':
break
conn.send()
#关闭连接
conn.close()
socket_server.close()
2.Socket客户端
主动连接服务端、可以发送消息、可以接收回复
#coding=utf-8
#客户端
import socket
#创建socket对象
socket_client=socket.socket()
#连接到服务端
socket_client.connect("localhost",8888)
while True:
#发送消息
msg=input("请输入要给服务端发送的消息:")
if msg=='exit':
break
socket_client.send("你好呀".encode("UTF-8"))
#接收消息
recv_data=socket_client.recv(1024)
print(f"服务端回复的消息是:{recv_data.decode('UTF-8')}")
#关闭连接
socket_client.close()
六、正则表达式
又称规则表达式,是使用单个字符串来描述、匹配某个句法规则的字符串,常被用来检索、替换那些符合某个模式(规则)的文本。(正则表达式就是使用字符串定义规则,并通过规则去验证字符串是否匹配。)
1.三个基本方法:match、search、findall
-
re.match(匹配规则,被匹配字符串)
从被匹配字符串开头进行匹配,匹配成功返回匹配对象(包含匹配的信息),匹配不成功返回空。
-
re.search(匹配规则,被匹配字符串)
搜索整个字符串,找出匹配的。从前向后,找到第一个后,就停止,不会继续向后
-
re.findall(匹配规则,被匹配字符串)
匹配整个字符串,找出全部匹配项;找不到返回空list:[]
-
re.match 与 re.search 的区别
re.match 只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回 None;而 re.search 匹配整个字符串,直到找到一个匹配。
# coding=utf-8 import re s="1python hello python" # match从头匹配 result=re.match("python",s) print(result) #<re.Match object; span=(1, 7), match='python'> # print(result.span()) # (1,7) # print(result.group()) # python # search搜索匹配 result=re.search("python",s) print(result) # findall搜索全部匹配 result=re.findall("python",s) print(result)
-
2.元字符匹配
2.1单字符匹配
字符 | 功能 |
---|---|
. | 匹配任意一个字符(除了\n),.匹配点本身 |
[ ] | 匹配[ ]中列举的字符 |
\d | 匹配数字,即0-9 |
\D | 匹配非数字 |
\s | 匹配空白,即空格、tab键 |
\S | 匹配非空白 |
\w | 匹配单词字符,即a-z,A-Z,0-9,- |
\W | 匹配非单词字符 |
2.2边界匹配
字符 | 功能 |
---|---|
^ | 匹配字符串开头 |
$ | 匹配字符串结尾 |
\b | 匹配一个单词的边界 |
\B | 匹配非单词边界 |
2.3分组匹配
字符 | 功能 |
---|---|
| | 匹配左右任意一个表达式 |
() | 将括号中字符作为一个分组 |
2.4数量匹配
字符 | 功能 |
---|---|
* | 匹配前一个规则的字符出现0至无数次 |
+ | 匹配前一个规则的字符出现1至无数次 |
? | 匹配前一个规则的字符出现0次或1次 |
{m} | 匹配前一个规则的字符出现m次 |
{m,} | 匹配前一个规则的字符出现最少m次 |
{m,n} | 匹配前一个规则的字符出现m到n次 |
# coding=utf-8
import re
#正则表达式使用元字符进行匹配
s1="fjafi jfoa 23#kj 234 jjf3"
#找出全部数字
result=re.findall(r'\d',s1)
print(result)
#找出特殊字符
result=re.findall(r'#',s1)
print(result)
#找出全部英文字母
result=re.findall(r'[a-zA-Z]',s1)
print(result)
#匹配账号,只能由字母和数字组成,长度限制6到10位
r='^[0-9a-zA-Z]{6,10}$'
s='aaf343'
print(re.findall(r,s))
#匹配QQ号,要求纯数字,长度5-11,第一位不为0
r='^[1-9][0-9]{4,10}$'
s='2933720448'
print(re.findall(r,s))
#匹配邮箱地址,只允许qq,163,gmail这三种邮箱地址
r=r'(^[\w-]+(\.[\w-]+)*@(qq|163|gmail)(\.[\w-]+)+$)'
s='2933720448@qq.com'
print(re.match(r,s))