当前位置: 首页 > news >正文

探索Python编程的技巧:多线程魔法、网络舞台、正则魔法阵与递归迷宫

一 多线程

1.1 进程和线程

  • 进程: 就是一个程序,运行在系统之上,称这个程序为一个运行进程,并分配进程ID方便系统管理。
  • 线程:线程是归属于进程的,一个进程可以开启多个线程,执行不同的工作,是进程的实际工作最小单位。
  • 操作系统中可以运行多个进程,即多任务运行
  • 一个进程内可以运行多个线程,即多线程运行

  • 进程之间是内存隔离的, 即不同的进程拥有各自的内存空间。
  • 线程之间是内存共享的,线程是属于进程的,一个进程内的多个线程之间是共享这个进程所拥有的内存空间的。
    在这里插入图片描述

1.2 并行、并发执行概念

  • 在Python中,多线程用于实现并行和并发执行任务。虽然多线程可以让你同时执行多个任务,但由于Python的全局解释锁(Global Interpreter Lock,GIL)的存在,多线程并不能实现真正的多核并行。然而,多线程仍然可以用于执行I/O密集型任务,因为在这些任务中,线程可能会在等待I/O操作完成时释放GIL,从而允许其他线程运行。

  • 并行执行:

    • 并行执行是指多个任务在同一时刻同时运行,各自独立地占用一个CPU核心。
    • 在Python中,由于GIL的存在,多线程并不适合用于CPU密集型任务的并行执行。
    • 多个进程同时在运行,即不同的程序同时运行,称之为:多任务并行执行
    • 一个进程内的多个线程同时在运行,称之为:多线程并行执行
  • 并发执行:

    • 并发执行是指多个任务交替执行通过快速切换执行任务的上下文来实现“同时”执行的错觉。
    • 这在处理I/O密集型任务时非常有效,因为线程可能会在等待I/O完成时让出CPU资源给其他线程。

1.3 多线程编程

  • 在Python中,可以使用threading模块来创建和管理多线程。

  • threading.Thread类可以创建一个线程对象,用于执行特定的任务函数。

  • threading.Thread类的一般语法和一些常用参数:

    thread_obj = threading.Thread(target=function_name, args=(), kwargs={}, daemon=False)
    # 启动线程
    thread_obj.start() 
    
  • target: 必需的参数用于指定线程要执行的函数(任务)。函数会在新线程中运行。

  • args: 可选参数用于传递给目标函数的位置参数,以元组形式提供。如果函数不需要参数,可以传递一个空元组或省略这个参数。

  • kwargs: 可选参数用于传递给目标函数的关键字参数,以字典形式提供。如果函数不需要关键字参数,可以传递一个空字典或省略这个参数。

  • daemon: 可选参数,布尔值,用于指定线程是否为守护线程。守护线程会在主线程结束时被终止,而非守护线程会等待所有线程完成后再终止。

  • 使用threading.Thread类创建线程对象并启动线程

import threading
import timedef print_numbers():for i in range(1, 6):print(f"Number: {i}")time.sleep(1)def print_letters():for letter in ['a', 'b', 'c', 'd', 'e']:print(f"Letter: {letter}")time.sleep(1)if __name__ == "__main__":thread1 = threading.Thread(target=print_numbers)thread2 = threading.Thread(target=print_letters)thread1.start()  # Start the first threadthread2.start()  # Start the second threadthread1.join()   # 用于阻塞当前线程,直到被调用的线程完成其执行thread2.join()   # 用于阻塞当前线程,直到被调用的线程完成其执行print("All threads completed")
  • 在这个示例中,创建了两个线程对象,每个线程对象都关联一个不同的任务函数(print_numbersprint_letters)。然后启动这两个线程,并等待它们完成。最后,我们输出一个提示,表示所有线程都已完成。

  • thread1thread2 是两个线程对象,而 thread1.join()thread2.join() 是在主线程中调用的。当调用这些方法时,主线程会阻塞,直到对应的线程(thread1thread2)完成了它们的执行。

  • thread1.join()thread2.join() 语句确保在两个子线程执行完成后,主线程才会输出 “All threads completed” 这条消息。如果不使用 join(),主线程可能会在子线程还没有完成时就继续执行,导致输出消息的时机不确定。

1.4 补充:join()方法

  • 在多线程编程中,join() 方法用于阻塞当前线程,直到被调用的线程完成其执行。具体来说,thread1.join() 表示当前线程(通常是主线程)会等待 thread1 线程完成后再继续执行。

  • 这种等待的机制可以确保主线程在所有子线程执行完成后再继续执行,从而避免可能出现的线程之间的竞争条件和不确定性。这在需要等待所有线程完成后进行进一步操作或获取线程执行结果时非常有用。

1.5 并行、并发实现演示

  • 并行执行多个任务演示:
import threadingdef task1():print("Task 1 started")# ... some code ...print("Task 1 finished")def task2():print("Task 2 started")# ... some code ...print("Task 2 finished")if __name__ == "__main__":thread1 = threading.Thread(target=task1)thread2 = threading.Thread(target=task2)thread1.start()thread2.start()thread1.join()thread2.join()print("All tasks completed")

  • 并发执行演示:
import threading
import timedef task1():print("Task 1 started")time.sleep(2)  # Simulate I/O operationprint("Task 1 finished")def task2():print("Task 2 started")time.sleep(1)  # Simulate I/O operationprint("Task 2 finished")if __name__ == "__main__":thread1 = threading.Thread(target=task1)thread2 = threading.Thread(target=task2)thread1.start()thread2.start()thread1.join()thread2.join()print("All tasks completed")

1.6 Thread参数传递使用演示

  • 当使用threading.Thread创建线程对象时,可以通过argskwargsdaemon参数传递不同类型的信息给线程。
  • 以下是针对每种参数的示例:
  1. 使用 args 参数传递位置参数:
import threadingdef print_numbers(start, end):for i in range(start, end + 1):print(f"Number: {i}")if __name__ == "__main__":thread1 = threading.Thread(target=print_numbers, args=(1, 5))thread2 = threading.Thread(target=print_numbers, args=(6, 10))thread1.start()thread2.start()thread1.join()thread2.join()print("All threads completed")
  1. 使用 kwargs 参数传递关键字参数:
import threadingdef greet(name, message):print(f"Hello, {name}! {message}")if __name__ == "__main__":thread1 = threading.Thread(target=greet, kwargs={"name": "Alice", "message": "How are you?"})thread2 = threading.Thread(target=greet, kwargs={"name": "Bob", "message": "Nice to meet you!"})thread1.start()thread2.start()thread1.join()thread2.join()print("All threads completed")
  1. 使用 daemon 参数设置守护线程:
import threading
import timedef count_seconds():for i in range(5):print(f"Elapsed: {i} seconds")time.sleep(1)if __name__ == "__main__":thread = threading.Thread(target=count_seconds)thread.daemon = True  # 设置线程为守护线程thread.start()# No need to join daemon threads, they will be terminated when the main thread endsprint("Main thread completed")
  • 将线程 thread 设置为守护线程(daemon = True)。这意味着当主线程结束时,守护线程也会被终止,而无需使用 join() 等待它完成。

二 网络编程

2.1 Socket初识

  • Python的套接字(Socket)编程是一种基本的网络编程技术,它可以在网络上建立连接并进行数据传输。
  • socket (简称 套接字) 是进程之间通信一个工具,进程之间想要进行网络通信需要socket。Socket负责进程之间的网络数据传输,是数据的搬运工。
    在这里插入图片描述

2.2 客户端和服务端

  • 2个进程之间通过Socket进行相互通讯,就必须有服务端和客户端
    • Socket服务端:等待其它进程的连接、可接受发来的消息、可以回复消息
    • Socket客户端:主动连接服务端、可以发送消息、可以接收回复
      在这里插入图片描述

2.3 创建socket对象详解

  • 在创建套接字对象时,通常是可以不指定参数的。如果没有指定参数,将会使用默认的参数,这些参数在 socket 模块中预先定义。默认情况下,socket 函数将创建一个 IPv4 的流式套接字。

  • 例如,以下代码将创建一个默认的 IPv4 TCP 套接字:

    import socket# 创建一个默认的 IPv4 TCP 套接字
    default_socket = socket.socket()# 后续代码中可以使用 default_socket 进行操作
    
  • 这种方式在很多情况下都是适用的,特别是当你只需要一个简单的 IPv4 TCP 套接字时。

    socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    1. socket:Python 的内置套接字模块,它提供了在网络上进行通信的基本功能。
    2. socket.AF_INET:表示套接字地址簇(Address Family),用于指定套接字使用的地址类型。AF_INET 表示使用 IPv4 地址。还可以使用 AF_INET6 来表示 IPv6 地址。
    3. socket.SOCK_STREAM:表示套接字的类型。SOCK_STREAM 表示这是一个流式套接字,它基于 TCP 协议提供了可靠的、面向连接的、双向的数据流传输。
  • 综合起来,socket.socket(socket.AF_INET, socket.SOCK_STREAM) 创建了一个基于 IPv4 地址和 TCP 协议的流式套接字对象,你可以使用这个套接字对象来建立连接、发送和接收数据。

  • 如果需要创建基于 UDP 协议的套接字,可以使用 socket.SOCK_DGRAM,例如:

    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    

2.4 accept()方法详解

  • accept() 方法是在服务器端套接字上调用的方法,用于接受客户端的连接请求。它会阻塞程序,直到有客户端尝试连接到服务器,然后返回一个新的套接字用于与该客户端进行通信,以及客户端的地址信息。

    client_socket, client_address = server_socket.accept()
    
    • accept():接受客户端的连接请求。当调用这个方法时,它会阻塞程序,直到有客户端连接到服务器。一旦有连接请求到达,该方法将返回两个值:一个是表示与客户端通信的新套接字对象,另一个是客户端的地址信息。
    • client_socket新创建的套接字对象,用于与连接的客户端进行通信(可以使用这个套接字来接收和发送数据)
    • client_address:元组类型,包含客户端的 IP 地址和端口号。例如,('192.168.1.100', 54321)
  • 一般来说,服务器在一个循环中使用 accept() 方法,以便能够接受多个客户端的连接。每当有新的客户端连接到服务器时,accept() 方法会返回一个新的套接字和客户端的地址,然后服务器可以将新套接字添加到连接池,与客户端进行通信。

  • 注意:accept() 方法在没有连接请求时会一直阻塞程序。如果你希望设置超时或者非阻塞的连接等待,你可以在创建服务器套接字后设置相应的选项。这样,在没有连接请求时调用 accept() 方法将立即返回,不会阻塞程序的执行。

  • 例如,在创建服务器套接字后可以使用以下代码将其设置为非阻塞模式:

    server_socket.setblocking(False)
    

2.5 发送信息方法详解

  • send() 方法和 sendall() 方法都用于在套接字上发送数据,但它们有一些不同之处。

send(data) 方法:

  • send() 方法是用于发送数据的基本方法,它接受一个字节流(bytes)作为参数,并尝试将数据发送到连接的对方。
  • 如果成功发送全部数据,该方法将返回发送的字节数。如果没有发送完全部数据,可能返回一个小于请求发送数据的字节数。
  • 如果在发送过程中出现问题(例如连接中断),send() 方法可能会引发异常。

sendall(data) 方法:

  • sendall() 方法也用于发送数据,但它更加健壮,会自动处理数据分片和重试。

  • 无论数据有多大,sendall() 方法会尽力将所有数据都发送出去,直到全部数据都被发送成功或发生错误。

  • 方法不会立即返回,而是在所有数据都发送成功后才返回 None。如果发生错误,它可能引发异常。

  • sendall() 方法在发送数据时会自动处理数据的分片,确保数据都被正确发送。

  • 在大多数情况下,如果想要简单地发送一小段数据,可以使用 send() 方法。然而,如果需要发送大量数据或者确保数据被完整、可靠地发送,那么使用 sendall() 方法会更好,因为它会自动处理数据分片和错误处理。

  • 使用 send() 方法:

    client_socket.send(b"Hello, server!")
    
  • 使用 sendall() 方法:

    data = b"Hello, server!"
    client_socket.sendall(data)
    

2.6 Socket编程演示

  • 服务器端代码:

    import socket# 1. 创建Socket对象
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 2. 绑定服务器地址和端口
    server_address = ('127.0.0.1', 12345)
    server_socket.bind(server_address)# 3. 开始监听端口 backlog=5 标识允许的连接数量,超出的会等待,可以不填,不填自动设置一个合理的值
    server_socket.listen(5)print("Waiting for a connection...")
    # 4. 接收客户端连接,获得连接对象
    client_socket, client_address = server_socket.accept()
    print(f"Connected to {client_address}")# 5. 客户端连接后,通过recv方法 接收并发送数据
    while True:data = client_socket.recv(1024).decode('utf-8')# recv接受的参数是缓冲区大小,一般给1024即可# recv方法的返回值是一个字节数组也就是bytes对象,不是字符串,可以通过decode方法通过UTF-8编码,将字节数组转换为字符串对象if not data:breakprint(f"Received: {data}")# 6. 通过client_socket对象(客户端再次连接对象),调用方法,发送回复消息msg = input("请输入你要和客户端回复的消息:")if msg == 'exit':breakclient_socket.sendall(msg.eccode("UTF-8"))# 7.关闭连接
    client_socket.close()
    server_socket.close()
    

  • 客户端代码:
    import socket# 1.创建socket对象
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 2.连接服务器地址和端口
    server_address = ('127.0.0.1', 12345)
    client_socket.connect(server_address)# 3.发送数据
    while True:# 发送消息msg = input("请输入要给服务端发送的消息:")if msg == 'exit':breakclient_socket.sendall(msg.encode("UTF-8"))# 4.接收返回消息recv_data = client_socket.recv(1024)  # 1024是缓冲区的大小,一般1024即可。 同样recv方法是阻塞的      print(f"服务端回复的消息是:{recv_data.decode('UTF-8')}")# 5.关闭连接
    client_socket.close()
    

三 正则表达式

3.1 正则表达式概述

  • 正则表达式,又称规则表达式(Regular Expression),是使用单个字符串来描述、匹配某个句法规则的字符串,常被用来检索、替换那些符合某个模式(规则)的文本。
  • 正则表达式就是使用:字符串定义规则,并通过规则去验证字符串是否匹配。
  • 比如,验证一个字符串是否是符合条件的电子邮箱地址,只需要配置好正则规则,即可匹配任意邮箱。通过正则规则: (^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$) 即可匹配一个字符串是否是标准邮箱格式

3.2 Python正则表达式使用步骤

  • 使用正则表达式的一些基本步骤和示例:
  1. 导入re模块:
import re
  1. 使用re.compile()编译正则表达式:
# `pattern_here`应该替换为实际正则表达式
pattern = re.compile(r'pattern_here')
  1. 使用编译后的正则表达式进行匹配:
text = "This is an example text for pattern matching."
result = pattern.search(text)
if result:print("Pattern found:", result.group())
else:print("Pattern not found.")

3.3 正则的基础方法

  • Python正则表达式,使用re模块,并基于re模块中基础方法来做正则匹配。

  • 匹配(Match):使用match()来从字符串的开头开始匹配。匹配成功返回匹配对象(包含匹配的信息),匹配不成功返回空

result = pattern.match(text)
  • 搜索(Search):使用search()来查找文本中的第一个匹配项。整个字符串都找不到,返回None
result = pattern.search(text)
  • 查找所有(Find All):使用findall()来找到所有匹配项,并返回一个列表。找不到返回空list: []
results = pattern.findall(text)
  • 替换(Replace):使用sub()来替换匹配项。
# `replacement`应该是希望替换匹配项的内容
new_text = pattern.sub(replacement, text)
  • 分割(Split):使用split()来根据匹配项分割字符串。
parts = pattern.split(text)
  • 在正则表达式中,你可以使用不同的元字符(例如.*+?[]()等)来构建复杂的模式,以便进行更精确的匹配。

  • 演示使用正则表达式从文本中提取所有的电子邮件地址

import retext = "Contact us at: john@example.com or jane@example.org for more information."pattern = re.compile(r'\b[\w.-]+@[\w.-]+\.\w+\b')
email_addresses = pattern.findall(text)for email in email_addresses:print(email)

3.4 元字符匹配

  • 单字符匹配
    在这里插入图片描述
    示例:
    字符串 s = "itheima1 @@python2 !!666 ##itcast3"
  • 找出全部数字: re.findall(r '\d', s)
  • 字符串的r标记,表示当前字符串是原始字符串,即内部的转义字符无效而是普通字符
  • 找出特殊字符: re.findall(r '\W', s)
  • 找出全部英文字母:re.findall(r '[a-zA-Z]', s)
  • []内可以写:[a-zA-Z0-9] 这三种范围组合或指定单个字符如[aceDFG135]

  • 数量匹配
    在这里插入图片描述
  • 边界匹配
    在这里插入图片描述
  • 分组匹配
    在这里插入图片描述

四 递归

  • 递归是一种编程技术(算法),即方法(函数)自己调用自己的一种特殊编程写法。在Python中,可以使用递归来解决许多问题,特别是那些可以被分解为相同或类似子问题的问题。
    在这里插入图片描述

  • 在使用递归时,需要确保定义递归基(base case),这是递归结束的条件,以避免无限循环。每次递归调用都应该将问题规模减小,使其朝着递归基的条件靠近。

  • 使用递归计算阶乘:

    def factorial(n):if n == 0:return 1  # 递归基else:return n * factorial(n - 1)  # 递归调用num = 5
    result = factorial(num)
    print(f"The factorial of {num} is {result}")
    
    • factorial 函数通过不断地调用自身来计算阶乘。当 n 达到递归基条件 n == 0 时,递归结束,不再调用自身。
  • 然而,递归并不总是最有效的解决方法,因为它可能会导致函数调用的嵌套层数过深,从而消耗大量的内存和处理时间。在一些情况下,使用循环或其他方法可能更有效。

  • 在编写递归函数时,要确保递归调用朝着递归基靠近,避免陷入无限循环,同时考虑性能方面的问题。

相关文章:

探索Python编程的技巧:多线程魔法、网络舞台、正则魔法阵与递归迷宫

一 多线程 1.1 进程和线程 进程: 就是一个程序,运行在系统之上,称这个程序为一个运行进程,并分配进程ID方便系统管理。线程:线程是归属于进程的,一个进程可以开启多个线程,执行不同的工作&…...

uniapp-微信小程序篇

uniapp-微信小程序篇 一、创建项目(以Vue3TS 项目为示例) 可以通过命令行的方式创建也可以通过HBuilderX进行创建(通过HBuilderX创建的项目建议选择最简单的模板),个人建议使用命令行方式。 (1) 命令行方式: npx degit dcloudio…...

使用pymupdf实现PDF内容搜索并显示功能

简介: 在日常工作和学习中,我们可能需要查找和提取PDF文件中的特定内容。本文将介绍如何使用Python编程语言和wxPython图形用户界面库来实现一个简单的PDF内容搜索工具。我们将使用PyMuPDF模块来处理PDF文件,并结合wxPython构建一个用户友好的…...

Dalsa线阵相机说明(Linea Color GigESeries 2k and 4K)

文章目录 一. Dalsa相机软件整体架构二. 相机编号说明以及软件要求三. 相机硬件参数三. 相机基本参数四. 软件参数设置列表1. Sensor Control Category2. I/O Control Category3. Counter and Timer Control Category4. Advanced Processing Control Category(1) 平场校正介绍(…...

图神经网络 day2 图的分类

图神经网络基础算法 1 GCN2 GraphSAGE2.1 采样:采样固定长度的邻居2.2 聚合2.3 GraphSAGE_minibatch2.4 GraphSAGE_embedding 3 GAT4. 图网络的分类4.1 递归图神经网络 RGNN4.2 图卷积神经网络GCN4.3 图注意力网络 GAT4.4 图自动编码 GAE4.5 图时空网络 GSTN4.6 图生…...

CentOS防火墙操作:开启端口、开启、关闭、配置

一、基本使用 启动: systemctl start firewalld 关闭: systemctl stop firewalld 查看状态: systemctl status firewalld 开机禁用 : systemctl disable firewalld 开机启用 : systemctl enable firewalld systemctl是…...

Chromium 如何在c++里面控制扩展加载

扩展安装 主要是通过UserMayLoad 函数控制,true允许加载,否则禁用 引自chromiun参考。【一般可以根据扩展ID禁用】 chrome\browser\extensions\standard_management_policy_provider.cc bool StandardManagementPolicyProvider::UserMayLoad( const Ext…...

分类预测 | MATLAB实现MTBO-CNN多输入分类预测

分类预测 | MATLAB实现MTBO-CNN多输入分类预测 目录 分类预测 | MATLAB实现MTBO-CNN多输入分类预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.MATLAB实现MTBO-CNN多输入分类预测 2.代码说明:基于登山队优化算法(MTBO)、卷积神经…...

操作符和表达式求值

目录 1.运算符的优先级和结合性 1.1运算符的优先级 1.2结合性 2.操作符的使用最终带来的是一个表达式的值 2.1.隐式类型转换(整型提升) 2.1.1整形提升的例子 2.2算术转换 1.运算符的优先级和结合性 运算符是编程语言中的基本元素之一,主…...

Unity Spine帧事件

SpinePro中添加事件帧 首先 选中右上角的层级树 然后选择事件选项 最后在右下角看到 新建 点击它 新建一个事件 点击左上角的设置按钮 弹出编辑窗口 编辑窗口 在右上角 动画栏 可以切换对应的动画 点坐边的那个小灰点来切换 亮点代表当前动画 选中帧 添加事件 点击对应事件…...

AE使用(一)

打开AE 点击“新建合成” 注意参数:宽度高度是视频是横屏还是竖屏。发布在抖音上,需要做出来竖屏效果;发布在视频网站中需要做出横屏效果。没用特殊需求,默认参数就行。 导入素材:左键双击“导入素材区”的空白部分。 …...

YOLOv5、YOLOv8改进:MobileViT:轻量通用且适合移动端的视觉Transformer

MobileViT: Light-weight, General-purpose, and Mobile-friendly Vision Transformer 论文:https://arxiv.org/abs/2110.02178 1简介 MobileviT是一个用于移动设备的轻量级通用可视化Transformer,据作者介绍,这是第一次基于轻量级CNN网络性…...

06-4_Qt 5.9 C++开发指南_MDI应用程序设计

文章目录 1. MDI简介2. 文档窗口类 QFormDoc 的设计3. MDI主窗口设计与子窗口的使用3.1 主窗口界面设计3.2 MDI子窗口的创建与加入3.3 QMdiArea 常用功能函数3.4 MDI的信号 4. 源码4.1 qwmainwindow.h4.2 qwmainwindow.cpp 1. MDI简介 传统的应用程序设计中有多文档界面(Multi…...

【SCI征稿】3区SCI,正刊,智能传感、机器学习、智能检测与测量等均可

影响因子:IF:2.0-3.0 期刊分区:JCR3区,中科院4区 检索情况:SCIE在检,正刊 征稿领域:智能技术在测量与检测中的应用研究,如: ● 复杂系统的智能传感和高级故障诊断 ●…...

神经网络ANN(MLP),CNN以及RNN区别和应用

1. Artificial Neural Network(ANN) 又称为Multilayer Perception Model(MLP) 2. CNN AAA 3. RNN 22 先占坑,后期再整理 References [1] CNN vs.RNN vs.ANN——浅析深度学习中的三种神经网络 - 知乎 [2] https://www.youtube.com/watch?vu7obuspdQu4 [3] 深…...

CUDA、cuDNN以及Pytorch介绍

文章目录 前言一、CUDA二、cuDNN三、Pytorch 前言 在讲解cuda和cuDNN之前,我们首先来了解一下英伟达(NVIDA)公司。 NVIDIA是一家全球领先的计算机技术公司,专注于图形处理器(GPU)和人工智能(…...

使用shift关键字,写一个带二级命令的脚本(如:docker run -a -b -c中的run)

省流:shift关键字 探索思路 最近有一个小小的需求,写一个类似于docker run -a -b -c这样的脚本,这个脚本名为doline,它本身可以执行(doline -a -b -c),同时又带有几个如run、init、start这样的…...

MySQL学习笔记 - 进阶部分

MySQL进阶部分 字符集的相关操作:字符集和比较规则:utf8与utf8mb4:比较规则:常见的字符集和对应的Maxlen: Centos7中linux下配置字符集:各个级别的字符集:执行show variables like %character%语…...

微信小程序实现左滑删除

一、效果 二、代码 实现思路使用的是官方提供的 movable-area:注意点,需要设置其高度,否则会出现列表内容重叠的现象。由于movable-view需要向右移动,左滑的时候给删除控件展示的空间,故 movable-area 需要左移 left:…...

安防视频监控有哪些存储方式?哪种存储方式最优?

视频监控系统涉及到大量的视频数据,需要对这些数据进行存储,以备日后查看或备份。视频监控的存储需求需要根据场所的实际情况进行选择,以保证监控数据的有效存储和日后的调阅、回溯。 当前视频监控的存储方式,通常有以下几种&…...

7.4.分块查找

一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...

(二)原型模式

原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

企业如何增强终端安全?

在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...

HashMap中的put方法执行流程(流程图)

1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...

基于 TAPD 进行项目管理

起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...

GitFlow 工作模式(详解)

今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...

免费数学几何作图web平台

光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

DBLP数据库是什么?

DBLP(Digital Bibliography & Library Project)Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高,数据库文献更新速度很快,很好地反映了国际计算机科学学术研…...

【Veristand】Veristand环境安装教程-Linux RT / Windows

首先声明,此教程是针对Simulink编译模型并导入Veristand中编写的,同时需要注意的是老用户编译可能用的是Veristand Model Framework,那个是历史版本,且NI不会再维护,新版本编译支持为VeriStand Model Generation Suppo…...

《Docker》架构

文章目录 架构模式单机架构应用数据分离架构应用服务器集群架构读写分离/主从分离架构冷热分离架构垂直分库架构微服务架构容器编排架构什么是容器,docker,镜像,k8s 架构模式 单机架构 单机架构其实就是应用服务器和单机服务器都部署在同一…...