问题原由
account_amount = 0 # 账户余额
def atm(num, deposit=True)
global account_amount
if deposit:
account_amount += num
print(f"存款:{num},账户余额:{account_amount}")
else:
account_amount -= num
print(f"取款:{num},账户余额:{account_amount}")
概述
在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们吧这个使用外部函数变量的内部函数称为闭包
简单闭包
def outer(logo):
def inner(mes):
print(f"<{logo}>{mes}<{logo}>")
return inner
fu = outer("flag")
fu("你好")
fu("Python")
def outer(num1):
def inner(num2):
nonlocal num1
num1 += num2
print(num1)
return inner
fu = outer(10)
fu(20)
def atm(account_money=0):
def save(num,deposit=True):
nonlocal account_money
if deposit:
account_money += num
else:
account_money -= num
print(f"账户当前月:{account_money}")
return save
fu = atm()
fu(300)
fu(300)
fu(100,False)
概述
装饰器也是一种闭包,其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能
原由
def sleep():
import random
import time
print("睡眠中....")
time.sleep(random.randint(1, 5))
装饰器的一般写法(闭包写法)
def outer(fun):
def inner():
print("准备睡觉...")
fun()
print("起床...")
return inner
def sleep():
import random
import time
print("睡眠中....")
time.sleep(random.randint(1, 5))
fn = outer(sleep)
fn()
装饰器的语法糖写法
def outer(func):
def inner():
print("准备睡觉...")
func()
print("起床...")
return inner
@outer
def sleep():
import random
import time
print("睡眠中....")
time.sleep(random.randint(1, 5))
sleep()
概述
单例模式
与Java一致,只需要该对象存在一个实例对象
class Str_tools:
pass
strTools = Str_tools()
from str_tools import strTools
s1 = strTools
s2 = strTools
print(id(s1))
print(id(s2))
工厂模式
当需要大量创建一个类实例的时候,可以使用工厂模式
class Person:
pass
class Worker(Person):
pass
class Student(Person):
pass
class Teacher(Person):
pass
class PersonFactory:
def getPerson(self, type):
if type == "w":
return Worker()
elif type == "s":
return Student()
else:
return Teacher()
factory = PersonFactory
worker = factory.getPerson("w")
Student = factory.getPerson("s")
Teacher = factory.getPerson("t")
概述
线程:线程是归属进程的,一个进程可以开启多个线程,执行不同的工作,是进程的实际工作最小单位
注意点:进程之间是存在隔离的,即不同的进程拥有各自的内存空间。线程之间是内存共享的,线程是属于进程的,一个进程的多个线程之间就是共享这个进程所拥有的内存空间
并行执行
多线程编程
import threading
threadObj = threading.Thread([group [, target [, name [, args [, kwargs]]]])
- group:暂时没作用,未来功能的预留参数
- target:执行的目标任务名
- args:以元组的方式给执行任务传参
- kwargs:以字典的方式给执行任务传参
- name:线程名,一般不设置
# 启动线程,让线程开始工作
threadObj.start()
def sing():
while True:
print("我在唱歌....")
time.sleep(1)
def dance():
while True:
print("我在跳舞....")
time.sleep(1)
if __name__ == '__main__':
# 创建一个线程执行唱歌函数
singStread = threading.Thread(target=sing)
# 常见一个线程执行跳舞函数
danceThread = threading.Thread(target=dance)
# 执行线程
singStread.start()
danceThread.start()
ef sing(mes):
while True:
print(mes)
time.sleep(1)
def dance(mes):
while True:
print(mes)
time.sleep(1)
if __name__ == '__main__':
# 创建一个线程执行唱歌函数
singStread = threading.Thread(target=sing, args=("我在唱歌....",))
# 常见一个线程执行跳舞函数
danceThread = threading.Thread(target=dance, kwargs={"mes":"我在跳舞....",})
# 执行线程
singStread.start()
danceThread.start()
客户端和服务端
Scoket服务端编程
import socket
# 创建Socket对象
serverSocket = socket.socket()
# 绑定ip地址和端口 参数为二元元组类型
serverSocket.bind(("localhost", 8888))
# 监听端口 # listen方法参数为整数类型,表示连接的数量
serverSocket.listen(1)
# 等待客户端链接
# result: cuple = serverSocket.accept()
# conn = result[0] 客户端和服务端的连接对象
# address = result[1] 客户端的地址信息
conn, address = serverSocket.accept() # accept()接受的是元组类型,分别为两个值,可以用两个变量来接受
# accept 是阻塞方法,等待客户端的连接,如果没有连接,则不会执行下面的代码
# 接收客户端信息 使用服务端与客户端的连接对象
while True:
print(f"接收到了客户端的信息,客户端的信息是:{address}")
data = conn.recv(1024).decode("UTF-8")
# recv接受的参数是缓冲区的大小,一般为1024
# recv方法的返回值为字节数组,不是字符串,通过decode方法传参为编码格式utf-8来转为字符串对象
print(f"客户端发来的信息是:{data}")
# 发送回复信息
mes = input("请输入你要和客户端回复的消息:") # encode可以将字符串转为字节数组对象
if mes == "exit":
break
conn.send(mes.encode("UTF-8"))
# 关闭链接
conn.close()
serverSocket.close()
import socket
# 创建socket对象
clientSocket = socket.socket()
# 连接到服务端
clientSocket.connect(("localhost", 8888))
# 发送信息
while True:
mes = input("请输入要发送给服务端的信息:")
clientSocket.send(mes.encode("UTF-8"))
if mes == "exit":
break
# 接受返回信息
revcMes = clientSocket.recv(1024) # 1024缓冲区的大小,同样recv为阻塞方法
print(f"服务端回复的信息为:{revcMes.decode('UTF-8')}")
# 关闭连接
clientSocket.close()
概述
三个基础方法
从被匹配字符串开头进行匹配,匹配成功返回匹配对象,匹配不成功返回空
import re
# match 从头匹配(匹配不上,返回None)
str = "mahaonan haonan"
result = re.match("mahaonan", str)
print(result) # <re.Match object; span=(0, 8), match='mahaonan'>
print(result.span()) # (0, 8)
print(result.group()) # mahaonan
搜索整个字符串,找出匹配的。从前向后,找到第一个就停止,不会继续匹配
str = "133haonan88888mahaonan888"
result = re.search("haonan", str)
print(result) # <re.Match object; span=(3, 9), match='haonan'>
print(result.span()) # (3, 9)
print(result.group()) # haonan
匹配整个字符串,找出全部匹配项
str = "133haonan88888mahaonan888"
result = re.findall("haonan", str)
print(result) #['haonan', 'haonan']
示例
s = "mahaonan @@@ 2354 haonan 777!!"
# 找出全部数字
re.findall(r"\d", s)
# 字符串的r标记,表示当前字符串是原始字符串,即内部的转义字符无效而是普通字符
# 找出特殊字符
re.findall(r"\W", s)
# 找出全部英文字母
re.findall(r"[a-zA-Z]", s)
[] 作用与Java一致
import re
# 匹配账号,只能由字母和数字组成,长度限制6-10位
r = "^[a-zA-Z0-9]{6,10}$"
str = input("请输入账号(由字母和数字组成,长度6-10):")
result = re.findall(r, str)
print(result)
# 匹配QQ号,要求纯数字,长度5-11,第一位不为0
print(re.findall(r"^[1-9]\d{4,10}$", input("请输入QQ号(纯数字,长度5-11,第一位不为0):")))
# 匹配邮箱地址,只允许qq、163、gmail着三种邮箱地址
r = r"(^[\w-]+(\.[\w-]+)*@(qq|163|gamail)(\.[\w-]+)+$)"
print(re.match(r, input("请输入邮箱地址:")))
import os
print(os.listdir("E:/TestPhoto")) # 将该文件下的所有文件名称打印出来
print(os.path.isdir("E:/TestPhoto")) # 判断该路径是否是文件夹
print(os.path.exists("E:/TestPhoto")) # 判断该路径的文件是否存在
def findAllDicrectory(path):
"""
指定路径,查找到所有的文件列表
:param path: 被判断的文件夹
:return: 包含全部的文件,如果不存在或者无文件,则返回空的list列表
"""
files = []
if os.path.exists(path):
directories = os.listdir(path)
for i in directories:
if os.path.isdir(f"{path}/{i}"):
files += findAllDicrectory(f"{path}/i")
else:
files.append(i)
else:
return files
return files
print(findAllDicrectory("E:/TestPhoto"))