python学习之路 - python进阶【闭包、装饰器、设计模式、多线程、socket、正则表达式】

目录

  • 一、python进阶
    • 1、闭包
        • a、概念
        • b、nonlocal关键字
        • c、优缺点
    • 2、装饰器
    • 3、设计模式
        • a、单例模式
        • b、工厂模式
    • 4、多线程
        • a、进程、线程
        • b、并行执行
        • c、多线程编程
    • 5、网络编程
        • a、概念
        • b、服务端开发
        • c、客户端开发
    • 6、正则表达式
        • a、概念
        • b、基础方法
        • c、元字符匹配
    • 7、递归

一、python进阶

1、闭包

a、概念

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

def outer(msg1):print(msg1)def inner(msg2):print(msg1 + "--" + msg2)return innerout = outer("这是msg1")
out("这是msg2")
out("这是第二个msg2")结果为:
这是msg1
这是msg1--这是msg2
这是msg1--这是第二个msg2
  • 如上述的案例,outer函数中的msg1只能作用域outer内部,外部无法获取到此变量
  • 外部函数的参数只能设置一次
  • 内部函数的变量可以设置多次,多次设置inner函数参数时,会多次执行inner函数内容
  • 内部函数只能使用外部函数的参数,此种写法无法更改参数内容
b、nonlocal关键字
  • 正常写法下,内部函数只能使用外部函数的参数,无法修改外部函数的参数,如果想要修改,则使用此关键字
  • 在内部函数中将外部函数的参数用nonlocal关键字修饰,则能更改参数的值
  • 多次调用内部函数时,多次的值会累加
def outer(msg1):def inner(msg2):nonlocal msg1msg1 += msg2print(f"{msg1}---{msg2}")return innerout = outer(10)
out(10)
out(10)结果为:
20---10
30---10
c、优缺点
  • 优点:
    • 无需定义全局变量即可实现通过函数,持续的访问修改某个值
    • 闭包使用的变量在函数内,难以被错误的调用修改
  • 缺点:
    • 由于内部函数持续引用外部函数的值,会导致部分内存空间不被释放,一直占用内存

2、装饰器

  • 介绍:装饰器其实也是一种闭包,在不破坏目标函数原有代码和功能的前提下,为目标函数增加新功能

案例:定义方法睡眠5秒,睡前睡后分别输出内容

普通写法from time import sleep
def func():print("开始")sleep(5)print("结束")
func()
装饰器简单写法def outer(func):def inner():print("开始")func()print("结束")return innerdef sleep1():from time import sleepsleep(5)out = outer(sleep1)
out()
装饰器高级写法def outer(func):def inner():print("开始")func()print("结束")return inner@outer
def sleep1():from time import sleepsleep(5)sleep1()

3、设计模式

设计模式是一种编程套路,可以极大方便程序的开发
最常见的设计模式就是面向对象

a、单例模式

在普通情况下,定义了一个类,多次实例化时,所得到的地址是不一样的

class Test:pass
test1 = Test()
test2 = Test()
print(test1 == test2)结果为:
False

如果想要多次实例化地址一样,就要用到单例模式
保证一个类只有一个实例,并且提供一个可以访问的全局访问点

第一步:test_tool.py文件中定义内容class Test:passtest_one = Test()
#第二步:test.py文件中定义内容from test_tool import test_one
test1 = test_one
test2 = test_one
print(test1 == test2)结果为:
True
b、工厂模式

当需要大量创建一个类的实例的时候,可以使用工厂模式

当有多个类时,每次都要自己分别定义类才会获得对应对象

class Person:pass
class Student:passperson = Person()
student = Student()

使用工厂模式,创建统一的创建对象的入口,便于代码维护
当发生修改时,只需要修改工厂类的方法即可

class Person:pass
class Student:passclass Factory:def get_person(self,type):if type == "s":return Student()else:return Person()person = Factory().get_person("p")
student = Factory().get_person("s")

4、多线程

a、进程、线程
  • 进程:就是一个程序,运行在系统之上,则称这个程序为一个运行进程,并分配进程ID方便系统管理
  • 线程:线程是归属于进程的,一个进程可以开启多个线程,执行不同的工作,是进程的实际工作量的最小单位
  • 注意:进程之间的内存是隔离的,则不同的进程拥有各自的内存空间。线程之间是内存共享的,线程属于进程,一个进程内的多个线程是共享这个进程所拥有的内存空间的
b、并行执行
  • 并行执行指同一时间做不同的工作
  • 进程之间就是并行执行的,操作系统可以同时运行很多程序,这些程序都是并行执行的
  • 线程也是可以并行执行的,同一个程序在同一时间做两件以上的事情,就称为多线程并行执行
c、多线程编程

python的多线程可以通过threading模块实现

基础语法

import threading
thread = threading.Thread(group=, target=, name=, args=, kwargs=, daemon=)
thread.start()group:暂时无用,未来功能的预留函数
target:执行的目标任务名,就是方法名
args:以元组的方式给执行任务传参
kwargs:以字典的方式给执行任务传参
name:线程名,一般不用设置

案例:创建两个方法并使用多线程同时执行

def one(msg):while True:print(msg)
def two(msg):while True:print(msg)import threading
#元组形式传参,只有一个元素时需要带上逗号才是元组
thread = threading.Thread(target=one, args=("one",))
#字典形式传参
thread2 = threading.Thread(target=two, kwargs={"msg": "two"})
thread.start()
thread2.start()结果为:
one
twoone
twoone
two
two
......

5、网络编程

a、概念

socket:是进程之间通信的一个工具,负责进程之间的网络数据传输,好比数据的搬运工
2个进程之间通过socket进行相互通讯,就需要有服务端和客户端
socket服务端:等待其他进程的链接,接收客户端发来的信息并回复消息socket客户端:主动连接服务端,发送消息给服务端,并接收返回的信息

b、服务端开发
# 第一步:创建socket对象
socket_server = socket.socket()
# 第二步:为服务端绑定ip地址和端口
socket_server.bind(("127.0.0.1", 8888))
# 第三步:监听端口。# 参数为允许连接的数量
socket_server.listen(1)
# 第四步:等待客户端连接。# 会返回一个二元元组,第一个元素为客户端和服务端的连接对象,第二个元素为客户端的地址信息# accept方法是阻塞方法,如果没有客户端链接会一直停留在这一行
socket_client, addr = socket_server.accept()
# 第五步:接收客户端发送的数据。# 参数为接收数据的最大字节数# 返回的时一个字节数组,不是字符串,可以通过decode方法转换为字符串
data = socket_client.recv(1024).decode("utf-8")
print(f"客户端接收的消息为:{data}")
# 第六步:向客户端发送数据。
socket_client.send("hello".encode("utf-8"))
# 第七步:关闭连接
socket_client.close()   #此关闭的是客户端的连接
socket_server.close()   #此关闭的是服务端
c、客户端开发
import socket
# 第一步:创建socket对象
socket_client = socket.socket()
# 第二步:连接到服务端
socket_client.connect(("127.0.0.1", 8888))
# 第三步:发送消息# 发送的内容默认是通过字节传输的,通过encode方法将字符串转换为字节
socket_client.send("hello".encode("utf-8"))
# 第四步:接收返回的消息# 参数为接收数据的最大字节数,此方法为阻塞的# 返回的时一个字节数组,不是字符串,可以通过decode方法转换为字符串
recv_data = socket_client.recv(1024).decode("utf-8")
print(f"服务端回复的消息为:{recv_data}")
# 第五步:关闭连接
socket_client.close()   #此关闭的是客户端的连接

6、正则表达式

a、概念
  • 正则表达式:也称为规则表达式,是使用单个字符串来描述、匹配某个句法规则的字符串,常被用来检索、替换那些符合某个模式的文本
  • 简单来说,正则表达式就是使用字符串来定义规则,并通过规则来验证字符串是否匹配
b、基础方法
  • re.match(匹配规则,被匹配字符串)
    • 从被匹配字符串的开头进行匹配,如果匹配成功则返回匹配对象,如果匹配不成功则返回空
    • 注意是从开头匹配,如果中间有对应字符串是不算的

案例:找出字符串中是否包含python开头的字符串

#情况一
import re
s = "python test python test"
result = re.match("python",s)
print(result)
print(result.span())		#这里是打印匹配字符串开头和结束的下标
print(result.group())		#这里是打印匹配的字符串内容结果为:
<re.Match object; span=(0, 6), match='python'>
(0, 6)
python
#情况二
import re
s = "1python test python test"
result = re.match("python",s)	#因为s是以1开头,所以无法匹配python字符串
print(result)结果为:
None
  • re.search(匹配规则,被匹配字符串)
    • 搜索整个字符串,找出匹配的。从前向后,找到第一个后就会停止
    • 如果匹配成功,会返回匹配的位置信息。如果未匹配成功,会返回None

案例:找出字符串中是否包含python开头的字符串

#情况一
import re
s = "111python test python test"
result = re.search("python",s)
print(result)
print(result.span())	#这里返回的是匹配字符串的开头和结尾下标位置
print(result.group())	#这里返回的是匹配的字符串结果为:
<re.Match object; span=(3, 9), match='python'>
(3, 9)
python
#情况二
import re
s = "111 test 2222 test"
result = re.search("python",s)
print(result)结果为:
None
  • re.findall(匹配规则,被匹配字符串)
    • 会匹配整个字符串,找出全部的匹配项
    • 如匹配成功会返回全部的匹配字符串内容。如果匹配不成功,会返回空List
#情况一
import re
s = "111python test python test"
result = re.findall("python",s)
print(result)结果为:
['python', 'python']
#情况二
import re
s = "111 test 2222 test"
result = re.findall("python",s)
print(result)结果为:
[]
c、元字符匹配

在上面我们进行了基础的字符串匹配,正则最强大的功能在于元字符匹配规则

  • 单字符匹配
字符功能
.匹配任意1个字符(除了\n),\. 就是匹配点本身
[ ]匹配 [ ] 中列举的字符
\d匹配数字,即 0-9
\D匹配非数字
\s匹配空白,即空格,tab键
\S匹配非空白
\w匹配单词字符,即 a-z、A-Z、0-9、_
\W匹配非单词字符
  • 数量匹配
字符功能
*匹配前一个规则的字符出现0至无限次
+匹配前一个规则的字符出现1至无限次
?匹配前一个规则的字符出现0次或1次
{m}匹配前一个规则的字符出现m次
{m,}匹配前一个规则的字符出现最少m次
{m,n}匹配前一个规则的字符出现m到n次
  • 边界匹配
字符功能
^匹配字符串开头
$匹配字符串结尾
\b匹配一个单词的边界
\B匹配非单词边界
  • 分组匹配
字符功能
|匹配左右任意一个表达式
( )将括号中字符作为一个分组
\b匹配一个单词的边界
\B匹配非单词边界

案例一:找出字符串中所有数字

import re
s = "test@@1452282!!###python"
# 找出全部数字
result = re.findall(r'\d',s)    #字符串前带上r的标记,表示字符串中转义字符无效,就是普通字符
print(result)结果为:
['1', '4', '5', '2', '2', '8', '2']

案例二:找出字符串中所有特殊字符

import re
s = "test@@1452282!!###python"
# 找出全部特殊字符
result = re.findall(r'\W',s)    #字符串前带上r的标记,表示字符串中转义字符无效,就是普通字符
print(result)结果为:
['@', '@', '!', '!', '#', '#', '#']

案例三:找出字符串中所有英文字母

import re
s = "test@@1452282!!###python"
# 找出全部英文字母
result = re.findall(r'[a-zA-Z]',s)    #字符串前带上r的标记,表示字符串中转义字符无效,就是普通字符
print(result)结果为:
['t', 'e', 's', 't', 'p', 'y', 't', 'h', 'o', 'n']

案例四:匹配字符串中只能包含字母和数字,并且长度为6到18位

import re
r = "^[0-9a-zA-Z]{6,18}$"
result = re.findall(r,"123adalg")
result2 = re.findall(r,"laeooeoaoao11111111oa44252")
print(result)
print(result2)结果为:
['123adalg']
[]

案例五:匹配字符串为纯数字,长度5到11位,第一位不为0

import re
r = "^[1-9][0-9]{4,10}$"
result = re.findall(r,"012345")
result2 = re.findall(r,"12355")
print(result)
print(result2)结果为:
[]
['12355']

案例六:匹配字符串的邮箱地址,只允许qq、163、gmail这三种邮箱地址

import re
r = r'(^[\w-]+(\.[\w-]+)*@(qq|163|gmail)(\.[\w-]+)+$)'
result = re.match(r,"12346@162.com")
result2 = re.match(r,"12346@163.com")
print(result)
print(result2.group())结果为:
None
12346@163.com

7、递归

递归:即方法(函数)自己调用自己的一种特殊的编程写法

案例:使用递归设计一个函数,获取一个路径下的所有文件名

import os
def get_all_files(path):"""获取指定路径下的所有文件:param path: 被判断的文件夹:return: list,包含全部的文件,如果目录不存在或者无文件则返回一个空list"""file_list = []if os.path.exists(path):for f in os.listdir(path):      # 循环路径下的所有文件和文件夹new_path = path + "/" + fif os.path.isdir(new_path):    # 判断是否为文件夹file_list += get_all_files(new_path)   # 递归调用else:file_list.append(new_path)else:print("路径不存在")return []return file_list

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

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

相关文章

OceanBase 安全体系解析之身份鉴别

本文作者&#xff1a;金长龙爱可生测试工程师&#xff0c;负责 DMP 产品的测试工作。 本文以MySQL为参照&#xff0c;详细阐述了OceanBase 在MySQL模式下的安全体系中&#xff0c;身份鉴别的能力&#xff0c;涵盖了身份鉴别机制、用户名的构成规则、密码的复杂度&#xff0c;以…

在Java中的动态绑定和静态绑定

动态绑定和静态绑定是两种方法调用的绑定机制静态绑定 静态绑定也称为早期绑定&#xff0c;是在编译时确定调用的方法。动态绑定 动态绑定也称为晚期绑定&#xff0c;是在运行时确定调用的方法。静态绑定用于编译时确定的方法调用&#xff0c;动态绑定是Java实现运行时多态的…

CISE|暴雨受邀出席第二十六届中国国际软件博览会

10月24日至26日&#xff0c;备受瞩目的第二十六届中国国际软件博览会&#xff08;简称CISE&#xff09;在国家会展中心&#xff08;天津&#xff09;圆满举办。CISE不仅汇聚了来自全国各地的顶尖软件企业和机构&#xff0c;还吸引了众多专家学者和行业精英共襄盛举&#xff0c;…

Cesium基础-(Entity)-(Box)

** 里边包含Vue、React框架代码详细步骤、以及代码详细解释 ** 3、Box 盒子 以下是 BoxGeometry 类的属性、方法和静态方法,以表格形式展示: 属性 属性名类型默认值描述minimumCartesian3盒子的最小 x, y, 和 z 坐标。maximumCartesian3盒子的最大 x, y, 和 z 坐标。vertex…

【PHP】PHP使用Modbus-Rut协议与RS485串口通信,向设备发送和接收数据

目录 一、前言 二、开发前说明 三、效果图 四、安装PHP扩展 五、安装phpModbus类库 六、通信逻辑 七、完整实例 一、前言 使用PHP语言与硬件设备通信交互&#xff0c;并向COM串口发送和接收数据。 前面写了三篇关于PHP与RS235和USB端口通信的文章&#xff0c;可以作为参…

现代数字信号处理I--最佳线性无偏估计 BLUE 学习笔记

目录 1. 最佳线性无偏估计的由来 2. 简单线性模型下一维参数的BLUE 3. 一般线性模型下一维参数的BLUE 4. 一般线性模型下多维参数的BLUE 4.1 以一维情况说明Rao论文中的结论 4.2 矢量参数是MVUE的本质是矢量参数中的每个一维参数都是MVUE 4.3 一般线性模型多维参数BLUE的…

视频剪辑哪个软件好用?推荐四款热门工具!!

在这个Vlog和短视频当道的互联网时代&#xff0c;掌握一款好用的视频剪辑软件就像拥有了打开创作世界的魔法钥匙。今天我们来聊聊视频剪辑软件&#xff0c;帮你成为剪辑达人哦&#xff01;接下来&#xff0c;给大家详细介绍四款常用且各具特色的视频剪辑软件&#xff0c;助你轻…

算法:利用前序序列和中序序列构造二叉树

题目 链接&#xff1a;leetcode链接 思路分析 前序遍历的顺序是&#xff1a;根 左子树 右子树 中序遍历的顺序是&#xff1a; 左子树 根 右子树 所以&#xff0c;我们可以通过前序遍历获得二叉树的根 可以通过中序遍历去分割二叉树&#xff0c;将二叉树分割成 左子树 根…

偷懒总结篇|贪心算法|动态规划|单调栈|图论

由于这周来不及了&#xff0c;先过一遍后面的思路&#xff0c;具体实现等下周再开始详细写。 贪心算法 这个图非常好 122.买卖股票的最佳时机 II(妙&#xff0c;拆分利润) 把利润分解为每天为单位的维度&#xff0c;需要收集每天的正利润就可以&#xff0c;收集正利润的区间…

HarmonyOS ArkTS与C++数据类型转换

1. HarmonyOS ArkTS与C数据类型转换 本文介绍了C与TS各自数据类型与互相之间的数据类型转换&#xff0c;在需要使用C模块时可以快速上手对各种数据类型进行转换。 1.1. 概述 HarmonyOS的主力开发语言是ArkTS&#xff0c;也提供了C语言的支持&#xff0c;对于一些能力&#xff…

1.3 面向对象 C++面试问题

1.3.1 简述一下什么是面向对象,面向对象与面向过程的区别 什么是面向对象 面向对象&#xff08;Object-Oriented Programming&#xff0c;OOP&#xff09;是一种编程范式&#xff0c;它通过将现实世界中的实体抽象为“对象”来组织代码。面向对象编程关注对象及其交互&#x…

D51【python 接口自动化学习】- python基础之模块与标准库

day51 模块的导入 学习日期&#xff1a;20241027 学习目标&#xff1a;模块与标准库 -- 66 模块的导入&#xff1a;如何使用其他人编写好的代码功能&#xff1f; 学习笔记 模块的作用 导入模块的方法 # 导入模块 # 方式一 import os # 获取当前的位置 print(os.getcwd())# …

arduino uno R3更换328pb-au芯片,烧录bootloader

使用usbasp烧录器进行烧录&#xff0c;解压 【免费】usbsap驱动以及软件资源-CSDN文库 安装驱动 然后打开软件 界面如下 1按步骤选中芯片&#xff0c; ATmega328P&#xff08;由于没有328PB&#xff0c;直接选这个也行&#xff09; 2查看spi接线&#xff0c; 3读取芯片id&a…

【SpringCloud】07-分布式事务与Seata

1. 分布式事务 2. Seata 3. 安装seata 配置数据库 CREATE DATABASE IF NOT EXISTS seata /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTIONN */; USE seata;------------------------------- The script used when storeM…

加强版 第一节图像二值化定义

本节课介绍了图像又彩色图像转变为彩色图像转变为灰度图像转变为黑色图像的转化过程。 灰度图像-单通道-取值范围为0-255 二值图像-单通道-取值0&#xff08;黑色&#xff09;-255&#xff08;白色&#xff09; 二值分割 有五种分割方式 如图所示 第一种&#xff1a;大于…

RabbitMQ 高级特性——事务

文章目录 前言事务配置事务管理器加上Transactional注解 前言 前面我们学习了 RabbitMQ 的延迟队列&#xff0c;通过延迟队列可以实现生产者生产的消息不是立即被消费者消费。那么这篇文章我们将来学习 RabbitMQ 的事务。 事务 RabbitMQ 是基于 AMQP 协议实现的&#xff0c;…

「C/C++」C/C++标准库之#include <cmath>数学库

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「C/C」C/C程序设计&#x1f4da;全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasoli…

认识线程 — JavaEE

目录 认识线程&#xff08;Thread&#xff09; 1 线程是什么? 2 为什么要有线程 3 进程和线程的区别 区别一 区别二 区别三 区别四 4. Java的线程和操作系统线程的关系 认识线程&#xff08;Thread&#xff09; 1 线程是什么? 一个线程就是一个 "执行流"。…

Excel-多表数据查找匹配(VLOOKUP)

&#x1f496;简介 Excel的VLOOKUP函数同样可以用来查找表格中的数据。VLOOKUP&#xff08;垂直查找&#xff09;是一个非常有用的函数&#xff0c;它可以在一个表格或数据表的一列中搜索特定的值&#xff0c;并返回与之在同一行上的另一列中的值。 &#x1f4d6;环境 WPS …

R语言机器学习算法实战系列(十二)线性判别分析分类算法 (Linear Discriminant Analysis)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍LDA的原理LDA的步骤教程下载数据加载R包导入数据数据预处理数据描述数据切割构建模型预测测试数据评估模型模型准确性混淆矩阵模型评估指标ROC CurvePRC Curve保存模型总结优点:缺…