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 inner

fn1 = 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_Init
        if deposit:
            amount_Init += num
            print(f"存款+{num},账户余额{amount_Init}")
        else:
            amount_Init -= num
            print(f"存款-{num},账户余额{amount_Init}")
    return atm

fn = account_Create()
fn(100)
fn(300, True)
fn(200, False)

优点

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

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

缺点

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

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

3.2 装饰器

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

def outer(func):
    def inner():
        print("11111")
        func()
        print("22222")
    return inner

def sleep():
    import random
    import time
    print("睡觉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 random
    import time
    print("睡觉Zzzz")
    time.sleep(random.randint(1,3))

sleep()

3.3 设计模式

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

  • 单例、工厂模式

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

  • 等模式

3.3.1 单例模式

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

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

# test02
class strTools:
    pass

str_tool = strTools()
# test
from test02 import str_tool

s1 = str_tool
s2 = str_tool
print(s1)
print(s2)
"""
<test02.strTools object at 0x000001BFBED43EF0>
<test02.strTools object at 0x000001BFBED43EF0>
"""
3.3.2 工厂模式

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

class Person:
    pass

class Worker(Person):
    pass
class Student(Person):
    pass
class Teacher(Person):
    pass

class 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 threading

thread_obj = threading.Thread([group [, target, [, name[, args[, kwargs]]]]])


thread_obj.start() # 启动线程,让线程开始工作
  • group:未来功能的预留参数

  • target:执行的目标任务名

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

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

  • name:线程名

import threading
import time

def 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 time

def 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接收的参数是缓冲区大小,一般1024
 recv方法的返回值是一个字节数组也是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':
        break
    print(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 re

str = "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()) # hello

str2 = "1hello python"
ret2 = re.match("hello", str2)
print(ret2) # None
print(ret2.span())
print(ret2.group())
  • search(匹配规则,被匹配字符串)

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

import re

str = "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()) # python

str2 = "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 re

str = "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 re

str = "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 os

def 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 + "/" + f
            if 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"))

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

风力发电自动化控制系统中的智能化技术应用研究

风力发电自动化控制系统中的智能化技术应用研究 随碳中和目标的提出和执行&#xff0c;风能发电作为新能源行业的核心部分&#xff0c;步入了它的黄金发展期。由于风能资源具有间歇性、随机性等特点&#xff0c;这给风电的高效利用带来了巨大挑战。为了增强风力发电系统的工作效…

Py深度学习基础|Numpy基础总结

注&#xff1a;本文来自菜鸟教程学习总结 一、数组属性 NumPy 的数组中比较重要 ndarray 对象属性有&#xff1a; 注意&#xff1a;使用reshape后&#xff0c;数组的结构&#xff08;即元素的排列顺序和内在连接&#xff09;没有改变&#xff0c;但因为返回的是一个视图&#…

PTA L1-009 N个数求和 【C++】【辗转相除法】【Python】

C&#xff1a; 辗转相除法&#xff1a; 每次算最小公倍数和最大公约数都是用的常规思路&#xff0c;本身是不会有错的&#xff0c;但是当数据很大时&#xff0c;就会出现错误&#xff0c;时间复杂度过高 辗转相除法&#xff0c;又称欧几里德算法&#xff08;Euclidean Algori…

接口压力测试 jmeter--增强篇(二)

前期准备 1. JMeter的插件的安装 下载Jmeter Plugins Manager对插件进行管理 &#xff08;1&#xff09;下载地址&#xff1a;https://jmeter-plugins.org/install/Install/ &#xff08;2&#xff09;下载后&#xff0c;将jar包放到jmeter包目录下/lib/ext目录下 &#xff0…

【YOLOv8改进[检测头Head]】YOLOv8的“新头”之动态头(DynamicHead)

目录 一 DynamicHead 二 YOLOv8的“新头”之动态头 1 总体修改 2 配置文件 3 训练 其他 一 DynamicHead 官方论文地址&#xff1a;https://arxiv.org/pdf/2106.08322.pdf 官方代码地址&#xff1a;GitCode - 开发者的代码家园 在计算机视觉应用中&#xff0c;目标检测…

启动appium服务的2种方法(python脚本cmd窗口)

1.通过cmd窗口命令来启动 2.通过python代码启动 2.1启动单个appium服务 2.2启动多个appium服务 3.端口说明 一.端口号设置Appium服务器端口&#xff1a;4723 bp端口&#xff1a;4724 Appium服务器端口&#xff1a;4725 bp端口&#xff1a;4726可以看到appium服务器端口和bp端…

SpringBoot(一)【入门】

前言 1、SpringBoot 快速入门 1.1、SpringBoot 简介 SpringBoot 是用来简化 Spring 应用的初始搭建以及开发过程 首先我们回顾一下 SpringMVC 项目的开发过程&#xff1a; 导入依赖&#xff08;javax.servlet-api 和 spring-webmvc&#xff09;Servlet 容器配置类&#xff…

VirtualBox虚拟机使用win11系统,忘记密码如何重置密码

1. 点击重启同时按住Shift&#xff08;按住不放&#xff09; 2. 直到出现下面的界面&#xff0c;释放Shift&#xff0c;并进入疑难解答 3. 进入高级选项 4. 进入命令提示符 5. 发现当前是在X盘&#xff1f; 6. 进入C:\Windows\System32 c: cd Windows\System32 7. 备份osk.exe…

SpringCloud系列(5)--SpringCloud微服务工程公共部分提取

前言&#xff1a;在上一章节中我们创建了两个个SpringCloud工程&#xff0c;但在两个工程中分别存在着一些重复的部分&#xff0c;例如重复的实体类&#xff08;如图所示&#xff09;&#xff0c;这样会造成系统的冗余&#xff0c;所以我们需要把公共的类提取到一个工程里&…

预约小程序新选择:强大后端管理功能一览

拥有一个功能齐全、操作便捷的小程序对于商家来说至关重要。为了满足广大商家的需求&#xff0c;乔拓云平台提供了丰富的模板资源&#xff0c;帮助用户快速搭建预约型小程序&#xff0c;并配备了强大的后端管理功能&#xff0c;让商家能够轻松管理预约订单&#xff0c;提升运营…

Centos7 ElasticSearch集群搭建

1. 服务器环境配置 1.1 配置hosts文件 3台服务器都要执行 vim /etc/hosts; # 将以下内容写入3台服务器hosts文件 192.168.226.148 es001 192.168.226.149 es002 192.168.226.150 es003 1.2 关闭防火墙 3台服务器都要执行 systemctl stop firewalld; systemctl disable…

【opencv】dnn示例-speech_recognition.cpp 使用DNN模块结合音频信号处理技术实现的英文语音识别...

模型下载地址&#xff1a; https://drive.google.com/drive/folders/1wLtxyao4ItAg8tt4Sb63zt6qXzhcQoR6 终端输出&#xff1a;&#xff08;audio6.mp3 、audio10.mp3&#xff09; [ERROR:00.002] global cap_ffmpeg_impl.hpp:1112 open VIDEOIO/FFMPEG: unsupported parameter…

# 从浅入深 学习 SpringCloud 微服务架构(一)基础知识

从浅入深 学习 SpringCloud 微服务架构&#xff08;一&#xff09;基础知识 1、系统架构演变&#xff1a; 1&#xff09;单体应用架构。如电商项目。 用户管理、商品管理、订单管理&#xff0c;在一个模块里。 优点&#xff1a;开发简单&#xff0c;快速&#xff0c;适用于…

Mac下brew安装php7.4

这里作者挂了梯子&#xff0c;所以很流畅&#xff01; brew的下载&#xff0c;可参考另外一篇博文&#xff5e;Homebrew 安装与卸载 1、将第三方仓库加入brew brew tap shivammathur/php2、安装指定版本的PHP brew install php7.43、替换Mac自带PHP环境并刷新环境变量 -> …

基于simulink的模拟锁相环和数字锁相环建模与对比仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 模拟锁相环&#xff08;PLL&#xff09;的基本原理 4.2 数字锁相环&#xff08;DPLL&#xff09;的基本原理 5.完整工程文件 1.课题概述 模拟锁相环和数字锁相环建模的simulink建模&#xff0c;对…

OpenHarmony UI动画-recyclerview_animators

简介 带有添加删除动画效果以及整体动画效果的list组件库 下载安装 ohpm install ohos/recyclerview-animatorsOpenHarmony ohpm 环境配置等更多内容&#xff0c;请参考如何安装OpenHarmony ohpm 包 使用说明 引入组件库 import { RecyclerView } from "ohos/recycler…

Qt/C++音视频开发70-无感切换通道/无缝切换播放视频/多通道流畅切换/不同视频打开无缝切换

一、前言 之前就写过这个方案&#xff0c;当时做的是ffmpeg内核版本&#xff0c;由于ffmpeg内核解析都是代码实现&#xff0c;所以无缝切换非常完美&#xff0c;看不到丝毫的中间切换过程&#xff0c;看起来就像是在一个通道画面中。其实这种切换只能说是取巧办法&#xff0c;…

排序算法之计数排序

目录 一、简介二、代码实现三、应用场景 一、简介 算法平均时间复杂度最好时间复杂度最坏时间复杂度空间复杂度排序方式稳定性计数排序O(nk )O(nk)O(nk)O(k)Out-place稳定 稳定&#xff1a;如果A原本在B前面&#xff0c;而AB&#xff0c;排序之后A仍然在B的前面&#xff1b; 不…

稀碎从零算法笔记Day52-LeetCode:从双倍数组中还原原数组

题型&#xff1a;数组、贪心 链接&#xff1a;2007. 从双倍数组中还原原数组 - 力扣&#xff08;LeetCode&#xff09; 来源&#xff1a;LeetCode 题目描述 一个整数数组 original 可以转变成一个 双倍 数组 changed &#xff0c;转变方式为将 original 中每个元素 值乘以 …

记录ubuntu20.04安装nvidia-525.85.05显卡驱动(学习笔记2024.4.15、4.16)

电脑&#xff1a;华硕天选X2024 显卡&#xff1a;4060Ti i5-14400F 架构&#xff1a;x86_64 我需要使用Linux系统使用IsaacSim进行仿真&#xff0c;所以安装的都是IsaacSim中的推荐版本。 一.对新鲜的电脑进行分盘 电脑刚到手&#xff0c;900多个G全在C盘里&#xff0c;给它…