Python进阶编程 --- 3.闭包、装饰器、设计模式、多线程、网络编程、正则表达式、递归

文章目录

    • 第三章:
      • 3.1 闭包
      • 3.2 装饰器
        • 语法糖写法
      • 3.3 设计模式
        • 3.3.1 单例模式
        • 3.3.2 工厂模式
      • 3.4 多线程
        • 3.4.1 进程、线程和并行执行
        • 3.4.2 多线程编程
      • 3.5 网络编程
        • 3.5.1 Socket
        • 3.5.2 服务端开发
        • 3.5.3 客户端开发
      • 3.6 正则表达式
        • 3.6.1 基础匹配
        • 3.6.2 元字符匹配
          • 单字符匹配:
          • 元字符匹配:
          • 边界匹配:
          • 分组匹配:
      • 3.7 递归

第三章:

3.1 闭包

在函数嵌套前提下,内部函数使用了外部函数的变量,并外部函数返回内部函数,把这个使用外部函数变量的内部函数称为闭包

def outer(logo):def inner(msg):print(f"<logo>{msg}<logo>")return innerfn1 = outer("Hello")
fn1("world")
fn1("World")fn2 = outer("Python")
fn2("hello")
fn2("Hello")

例:

def account_Create(amount_Init=0):def atm(num, deposit=True):nonlocal amount_Initif deposit:amount_Init += numprint(f"存款+{num},账户余额{amount_Init}")else:amount_Init -= numprint(f"存款-{num},账户余额{amount_Init}")return atmfn = account_Create()
fn(100)
fn(300, True)
fn(200, False)

优点

  • 无需定义全局变量就可实现通过函数,持续访问,修改某个值

  • 闭包使用的变量所用在函数内,难以被错误的调用修改

缺点

  • 内部函数持续引用外部函数的值,以至于这一部分内存空间不被释放,一直占用内存

在闭包函数中想要修改外部函数的变量值,需用nonlocal声明该外部变量

3.2 装饰器

作用:不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能

def outer(func):def inner():print("11111")func()print("22222")return innerdef sleep():import randomimport timeprint("睡觉Zzzz")time.sleep(random.randint(1,3))fn = outer(sleep)
fn()
语法糖写法
def outer(func):def inner():print("11111")func()print("22222")return inner
@outer
def sleep():import randomimport timeprint("睡觉Zzzz")time.sleep(random.randint(1,3))sleep()

3.3 设计模式

除了面向对象外,在编程中有很多既定的套路可方便开发,称为设计模式

  • 单例、工厂模式

  • 建造者、状态、备忘录、访问者、模板、代理模式

  • 等模式

3.3.1 单例模式

作用:确保某一个类只有一个实例存在

保证一个类只有一个实例,并提供一个访问的全局访问点。

# test02
class strTools:passstr_tool = strTools()
# test
from test02 import str_tools1 = str_tool
s2 = str_tool
print(s1)
print(s2)
"""
<test02.strTools object at 0x000001BFBED43EF0>
<test02.strTools object at 0x000001BFBED43EF0>
"""
3.3.2 工厂模式

当需要大量创建一个类的实例时,可使用工厂模式。从原生的使用类去构造去创建对象的形式,迁移到,基于工厂提供的方法去创建对象的形式。

class Person:passclass Worker(Person):pass
class Student(Person):pass
class Teacher(Person):passclass Factory:def get_person(self,person_Type):if person_Type == 'w':return Worker()elif person_Type == 's':return Student()else:return Teacher()factory = Factory()
worker = factory.get_person('w')
student = factory.get_person('s')
teacher = factory.get_person('t')
  • 大批量创建对象时有统一的入口,易于代码维护

  • 当发生变化时,只需修改工厂类的创建方法即可

  • 符合现实世界的模式,由工厂来制作产品(对象)

3.4 多线程

3.4.1 进程、线程和并行执行

进程:一个程序,运行在系统之上,那便称该程序为一个运行进程,并分配进程ID方便管理系统

线程:线程归属于进程,一个进程可开启多个线程,执行不同的工作,是进程的实际工作最小单位

多任务运行:操作系统中可运行多个进程
多线程运行:一个进程内可运行多个线程

进程之间是内存隔离的,不同的进程拥有各自的内存空间。

线程之间是内存共享的,线程是属于进程的,一个进程内的多个线程之间是共享该进程所拥有的内存空间

并行执行:同一时间做不同的工作

多任务同时运行,即不同的程序同时运行,称为:多任务并行执行

一个程序在同一时间做两件或更多件不同的事情时,称为:多线程并行执行

3.4.2 多线程编程

通过threading模块实现

import threadingthread_obj = threading.Thread([group [, target, [, name[, args[, kwargs]]]]])thread_obj.start() # 启动线程,让线程开始工作
  • group:未来功能的预留参数

  • target:执行的目标任务名

  • args:以元组方式给执行任务传参

  • kwargs:以字典方式给执行任务传参

  • name:线程名

import threading
import timedef Coffee():while True:print("喝咖啡")time.sleep(1)def Tea():while True:print("喝茶")time.sleep(1)# 创建进程
coffee_thread = threading.Thread(target=Coffee)
tea_thread = threading.Thread(target=Tea)# 执行进程
coffee_thread.start()
tea_thread.start()
import threading
import timedef Coffee(msg):while True:print(msg)time.sleep(1)def Tea(msg):while True:print(msg)time.sleep(1)# 创建进程
coffee_thread = threading.Thread(target=Coffee, args=("喝咖啡"))
tea_thread = threading.Thread(target=Tea, args={"msg": "喝茶"})# 执行进程
coffee_thread.start()
tea_thread.start()

3.5 网络编程

3.5.1 Socket

socket:进程之间通讯的一个工具,进程之间想要进行网络通信需要socket

socket负责进程之间的网络数据传输

在这里插入图片描述

2个进程之间通过Socket进行相互通信,必须有服务端和客户端

Socket服务端:等待其他进程的连接、可接收发来的信息、可回复信息

Socket客户端:主动连接服务器、可发送信息、可接收回复

在这里插入图片描述

3.5.2 服务端开发

步骤

1.创建socket对象

2.绑定socket_server到指定IP地址和端口

3.服务端开始监听端口

4.接收客户端连接,获取链接对象

5.连接客户端后,通过recv方法,接收客户端所发来的信息

6.通过conn,调用send方法可回复消息

7.conn和socket_server对象调用close方法,关闭连接


import socket # 导包
socket_server = socket.socket() # 创建socket对象
socket_server.bind(("localhost", 8888)) # 绑定IP地址和端口
socket_server.listen(1) # 监听端口
# listen方法内接收一个整数传参数,表示接收的链接数量
conn, address = socket_server.accept() # 接收客户端连接,获取连接对象
"""result: tuple = socket_server.accept()conn = result[0]   # 客户端和服务端的连接对象address = result[1]# 客户端的地址信息accept方法返回的是二元元组(连接对象,客户端地址信息)可通过变量1,变量2 = socket_server.accept()的形式,直接接收二元元组内的两个元素accept()方法,是阻塞的方法,等待客户端的连接,若没有连接,卡着不执行了
"""
print(f"接收到客户端的连接,信息是:{address}")
data: str = conn.recv(1024).decode("UTF-8") # 连接客户端后,通过recv方法,接收客户端所发来的信息
""""接收客户端信息,使用客户端和服务端的本次连接对象,而非socket_server对象recv接收的参数是缓冲区大小,一般1024recv方法的返回值是一个字节数组也是Bytes对象,不是字符串,可通过decode方法UTF-8编码,将字节数组转换为字符串对象
"""
print(f"客户端发来的信息是:{data}")
msg = input("请输入和客户端回复的信息:").encode("UTF-8") # 发送回复信息
conn.send(msg) # 通过conn,调用send方法可回复消息
conn.close() # conn和socket_server对象调用close方法,关闭连接
socket_server.close()

优化:

import socket
socket_server = socket.socket()
socket_server.bind(("localhost", 8888))
socket_server.listen(1)
conn, address = socket_server.accept()
print(f"接收到客户端的连接,来的{address}")
while True:data = conn.recv(1024).decode("UTF-8")if data == 'exit':breakprint(f"发送来的信息是:{data}")reply = input("请输入回复的信息:").encode("UTF-8")conn.send(reply)
conn.close()
socket_server.close()

在这里插入图片描述
在这里插入图片描述

3.5.3 客户端开发

步骤

1.创建socket对象

2.连接到服务端

3.发送消息

4.接收并返回消息

5.关闭连接

import socket # 导包
socket_client = socket.socket() # 创建socket对象
socket_client.connect(("localhost", 8888)) # 连接到服务器
socket_client.send("你好".encode("UTF-8")) # 发送消息
data = socket_client.recv(1024) # 接收信息并返回
print(f"服务端返回的信息为:{data}") #
socket_client.close() # 关闭连接

3.6 正则表达式

正则表达式又称规则表达式,是使用单个字符串来描述、匹配某个句法规则的字符串,常被用来检索、替换哪些符号某个模式的文本。

使用:字符串定义规则,并通过规则去验证字符串是否匹配

3.6.1 基础匹配

三个基础方法

<1>match

<2>search

<3>findall

  • re.match(匹配规则,被匹配字符串)

从被匹配字符串开头进行匹配,匹配成功返回匹配对象,不成功则返回空

import restr = "hello python"
ret = re.match("hello", str)
print(ret) # <re.Match object; span=(0, 5), match='hello'>
print(ret.span()) # (0, 5)
print(ret.group()) # hellostr2 = "1hello python"
ret2 = re.match("hello", str2)
print(ret2) # None
print(ret2.span())
print(ret2.group())
  • search(匹配规则,被匹配字符串)

搜索整个字符串,找出匹配的字符串,从前往后,找到第一个后就停止,不会继续向后

import restr = "hello python"
ret = re.search("python", str)
print(ret) # <re.Match object; span=(6, 12), match='python'>
print(ret.span()) # (6, 12)
print(ret.group()) # pythonstr2 = "hello 1python"
ret2 = re.search("python", str2)
print(ret2) # None # <re.Match object; span=(7, 13), match='python'>
print(ret2.span()) # (7, 13)
print(ret2.group()) # python
  • findall(匹配规则,被匹配字符串)

匹配整个字符串,找出全部匹配项,找不到返回空list:[]

import restr = "hello python"
ret = re.findall("python", str) 
print(ret) # ['python']str2 = "hello 1python"
ret2 = re.search("world", str2)
print(ret2) # None
3.6.2 元字符匹配
单字符匹配:
字符功能
.匹配任意1个字符,除了\n
[]匹配[]内列举的字符
\d匹配数字,0-9
\D匹配非数字
\s匹配空白,空格、tab键
\S匹配非空白
\w匹配单词字符,a-z、A-Z 、0-9、_
\W匹配非单词字符
import restr = "hello 2python"
ret = re.findall(r'[e-h]', str) # 字符串前加上r标记,表示字符串中转义字符无效,为普通字符
print(ret) # ['h', 'e', 'h']
元字符匹配:
字符功能
*匹配前一个规则的字符出现0次至无数次
+匹配前一个规则的字符出现1次至无数次
匹配前一个规则的字符出现0次或1次
{m}匹配前一个规则的字符出现m次
{m,}匹配前一个规则的字符出现至少m次
{m, n}匹配前一个规则的字符出现m至n次
边界匹配:
字符功能
^匹配字符串开头
$匹配字符串结尾
\b匹配一个单词的边界
\B匹配非单词边界
分组匹配:
字符功能
()括号中字符作为一个分组
import re
# 1
r = '^[0-9a-zA-Z]{6,10}$' # 只能由字母和数字组成,长度范围6-10位
str = '123456abc'
print(re.findall(r, str)) # ['123456abc']# 2 纯数字,长度5-10位,第一位不可为0
r = '^[1-9][0-9]{5,9}$'
str = '12345678'
print(re.findall(r, str)) # ['12345678']# 3 匹配邮箱地址,只允许168、qq邮箱地址
r = r'(^[\w-]+(\.[\w-]+)*@(163|qq)(\.[\w-]+)+$)'
str = 'ziqi@163.com'
print(re.findall(r, str)) # [('ziqi@163.com', '', '163', '.com')]

3.7 递归

方法/函数自己调用自己的一种特殊编程写法

def func():if 1:func()return 0
import osdef test_os():print(os.listdir("D:/test"))       # 列出路径下的内容print(os.path.isdir("D:/test/a"))  # 判断指定路径是不是文件夹print(os.path.exists("D:/test"))   # 判断指定路径是否存在def get_files(path):"""从指定的文件中用递归的方式,获取全部的文件列表:param path: 被判断的文件夹:return: 包含全部文件,若目录不存在或无文件则返回一个空list[]"""file_list = []if os.path.exists(path):for f in os.listdir(path):new_path = path + "/" + fif os.path.isdir(new_path):get_files(new_path)else:file_list.append(new_path)else:print(f"指定目录{path}不存在")return []print(get_files("D:/test"))

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/450.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

fopen/fwrite/fread/open/write/read的区别

fopen和Open,read和fread,write和fwrite有什么区别,很多人都会弄混了,而这经常会带来一些问题。所以在这里理清他们的关系是很有必要的。 open/read/write是Linux提供的系统调用,用户态的程序只能通过这些接口来访问文件系统层。而fopen/fread/fwrite是C库提供的文件读写接…

IT如何与业务双向奔赴,高效并驱共“盈”企业发展

随着经济和技术的飞速发展&#xff0c;在当前数字化时代中&#xff0c;如何进行有效的数字化转型、运用新技术&#xff0c;特别是让AI技术融入企业的具体业务场景、快速实现应用场景的落地、确保企业不落后于时代发展&#xff0c;是每一位CIO都会面临的一项挑战。 IT部门在企业…

springboot 载入自定义的yml文件转DTO

改进方法&#xff0c;直接spring注入 import cn.hutool.json.JSONUtil; import org.springframework.beans.factory.config.YamlMapFactoryBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import …

掌握Java异常处理:编写更健壮的应用程序

Java 异常处理机制是 Java 编程语言的核心特性之一&#xff0c;它为开发者提供了管理和处理运行时错误的有效方式。本文将深入探讨 Java 异常的类型、处理方法以及最佳实践&#xff0c;帮助你编写更健壮、可维护的 Java 应用程序。 1. 异常概念 异常是程序执行过程中出现的非正…

【强化学习的数学原理-赵世钰】课程笔记(十)Actor-Critic 方法

目录 一.最简单的 actor-critic&#xff08;QAC&#xff09;&#xff1a;The simplest actor-critic (QAC) 二.Advantage actor-critic (A2C) 三.Off-policy actor-critic 方法 四. Deterministic actor critic(DPG) Actor-Critic 方法把基于 value 的方法&#xff0c;特别…

C语言中的控制语句(分支语句 if、switch、三目运算符)

程序执行的三大流程 顺序 : 从上向下&#xff0c; 顺序执行代码分支 : 根据条件判断&#xff0c; 决定执行代码的分支循环 : 让特定代码重复的执行 分支语句 条件语句用来根据不同的条件来执行不同的语句&#xff0c;C语言中常用的条件语句包括if语句和switch语句。 if 语句…

网络靶场实战-恶意程序自启动

简介 当恶意程序入侵目标为个人计算机时&#xff0c;相较于服务器&#xff0c;个人计算机对关机或重启操作更加频繁&#xff0c;关机时计算机所有的进程都会被结束&#xff0c;因此恶意程序需要配置自启动来使自己在每次开机时能够被运行。 本篇介绍一个恶意样本(b8090d7d12d…

Docker向harbor上传大镜像的413报错

文章目录 一、背景二、问题三、处理1.调整harbor相关大小2.正向代理的nginx参数 一、背景 最近遇到了个需求&#xff0c;某厂商的系统模块以容器模式部署在我们的内网环境中&#xff0c;厂商为我们提供了一个公网仓库&#xff0c;需要我们自己下载相关镜像。因此&#xff0c;获…

快速找到销售爆款!淘宝商品关键词搜索API接口为你开启财富之门

在如今的电商时代&#xff0c;淘宝作为中国最大的网络购物平台&#xff0c;吸引了数以亿计的用户。对于卖家而言&#xff0c;如何快速找到热销商品&#xff0c;成为其成功的关键。淘宝商品关键词搜索API接口就是为了满足这一需求而诞生的工具&#xff0c;联讯数据为卖家提供了全…

C# 动态加载dll

方式1 using System; using System.Reflection;class Program {static void Main(){string dllPath "path/to/your/library.dll"; // 替换为你的DLL文件路径Assembly myAssembly Assembly.LoadFile(dllPath);Type myType myAssembly.GetType("YourNamespace…

番外篇 | YOLOv8改进之在C2f中引入即插即用RepViTBlock模块 | CVPR2024清华RepViT

前言:Hello大家好,我是小哥谈。YOLOv8是一种基于深度学习的实时物体检测算法,其通过将物体检测任务转化为目标框回归问题,并使用卷积神经网络实现高效的特征提取和目标分类。然而,YOLOv8在处理一些复杂场景和小目标时可能存在一定的性能限制。为了克服YOLOv8的局限性,清华…

JMM与内存屏障

一、cpu多核并发缓存架构解析 JMM内存模型&#xff1a;java多线程内存模型跟cpu缓存模型类似&#xff0c;是基于cpu缓存模型来建立的&#xff0c;java线程内存模型是标准化的&#xff0c;屏蔽掉了底层不同计算机的区别 JMM数据原子操作 read(读取)&#xff1a;从主内存读取数据…

算法题解记录17+++完全平方数

这是楼主第一次不靠题解&#xff0c;挑战动态规划的中等题目&#xff0c;虽然最终结果只超过了5%的人&#xff0c;不过我也很满意了。 本题楼主首先采用朴素的递归型动态规划&#xff0c;接着优化算法&#xff0c;使用借助HashMap存储临时数据的递归型动态规划&#xff0c;几次…

基于1-wire总线的多路温度监测系统

前言 在现代工业生产和环境监测中&#xff0c;温度是一个关键的参数&#xff0c;它直接影响到生产过程的稳定性和产品质量。为了确保温度控制在安全和有效的范围内&#xff0c;需要一种可靠且高效的多路温度监测系统。随着微电子技术和传感器技术的发展&#xff0c;基于1-Wire…

Redis key(BigKey、MoreKey)的存储策略

1. MoreKey 案例 1.1 大批量往 redis 里面 插入2000w 测试数据key (1) Linux Bash 下面执行&#xff0c;插入 100w rootspray:~# for((i1;i<100*10000;i)); do echo "set k$i v$i" >> /tmp/redisTest.txt; done; 查看 rootspray:~# more /tmp/redisTest.…

elementui单个输入框回车刷新整个页面

<!-- 搜索 --> <el-form :model"queryParams" ref"queryForm" :inline"true"><el-form-item label"名称" prop"nameLike"><el-input v-model"queryParams.nameLike" placeholder"请输入…

Arcgis Pro2.5安装教程(内含安装文件)

​最近处理的数据量大&#xff0c;发现arcmap这种老产品属实是不行了&#xff0c;相比于下一代的Arcgis Pro,不但运行速度慢&#xff0c;也容易遇到突然关闭的问题&#xff0c;之前基于团队的选择也没办法&#xff0c;最近实在是被数据搞得无语了&#xff0c;一鼓作气装上了Arc…

319_C++_使用QT自定义的对话框,既能选择文件也能选择文件夹,为什么使用QListView和QTreeView来达成目的?

解析 1: 在 Qt 中,QFileDialog::setOption 方法用于设置文件对话框的一些选项,以改变其行为或外观。QFileDialog::DontUseNativeDialog 是这些选项之一,当设置为 true 时,它会告诉 QFileDialog 不要使用操作系统提供的原生文件对话框,而是使用 Qt 自己实现的对话框样式。…

WAF攻防-漏洞发现协议代理池GobyAwvsXray

知识点 1、Http/s&Sock5协议 2、Awvs&Xray&Goby代理 3、Proxifier进程代理使用 4、Safedog&BT&Aliyun防护在漏洞发现中&#xff0c;WAF会对三个方向进行过滤拦截&#xff1a; 1、速度频率问题&#xff08;代理池解决&#xff09; 2、工具的指纹被识别&am…

MySQL查询重复数据获取最新数据

方法一&#xff1a; 1055 - Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column ‘se_jck的博客-CSDN博客 这个错误是由于 MySQL 的新版本中默认开启了ONLY_FULL_GROUP_BY模式&#xff0c;即在 GROUP BY 语句中的 SELECT 列表中&…