系列篇章🎉
| No. | 文章 |
|---|---|
| 1 | 【Python】基础知识(详细)🚀 |
| 2 | 【Python】基础 - 循环、容器类型🚀 |
| 3 | 【Python】基础 - 推导式、函数🚀 |
| 4 | 【Python】基础 - 文件、异常、模块🚀 |
| 5 | 【Python】进阶 - 面向对象(详细)🚀 |
| 6 | 【Python】进阶 - 闭包、装饰器、深浅拷贝🚀 |
目录
一、计算机网络概述
1.1 网络编程三要素
IP地址(Internet Protocol Address)
- IP 地址是用来标识网络中唯一一台设备的地址。在 TCP/IP 网络中,每台设备必须有一个唯一的 IP 地址才能进行通信
- IPv4:32位地址,通常以点分十进制表示(如
192.168.1.1) - IPv6:128位地址,用于解决 IPv4 地址不足的问题(
如2001:0db8:85a3::8a2e:0370:7334)
端口号(Port Number)
- 端口号用来标识运行在目标设备上的特定应用程序或服务。它是一个 16 位整数(范围为 0~65535)
- 常见服务有固定端口,例如:HTTP:80、HTTPS:443、FTP:21、SSH:22
- 一般程序员开发应用程序使用的端口号成为动态端口号范围是1024至65535,不过建议使用8000以后的
协议(Protocol)
协议定义了数据在网络中的传输规则和格式,常见的网络协议包括:
- TCP(Transmission Control Protocol):面向连接、可靠传输、按序交付,适合对数据准确性要求高的场景(如网页浏览、文件传输)
- UDP(User Datagram Protocol):无连接、不可靠传输、速度快,适合实时性要求高的场景(如音视频传输、游戏)
1.2 编码转换
在计算机网络中,数据是以二进制进行传输的。所以在网络传输数据的过程中,数据需要先转化为二进制(bytes)数据类型。
| 方法 | 类型转换方向 | 作用 |
|---|---|---|
encode() | str → bytes | 字符串编码成字节 |
decode() | bytes → str | 字节解码成字符串 |
字符串编码:
str.encode([encoding='utf-8'])
字节解码:
bytes.decode([encoding='utf-8'])
encoding:指定解码格式,默认是 'utf-8' 。
二、TCP开发基础

2.1 socket类
socket 类是进行网络编程的核心工具之一,它封装了底层的 TCP/IP 协议栈,使用socket可以方便地进行客户端-服务器通信。
# 1. 导入socket模块
import socket
# 2. 创建客户端socket对象使用socket类
socket.socket(AddressFamily, Type)
| 参数 | 含义 |
|---|---|
| AddressFamily | 地址族(Address Family),常用 socket.AF_INET(IPv4)或 socket.AF_INET6(IPv6) |
| Type | 套接字类型,常用 socket.SOCK_STREAM(TCP)或 socket.SOCK_DGRAM(UDP) |
2.2 服务器端
主动发起建立连接请求的是客户端程序,等待接受连接请求的是服务端程序。
| 方法名 | 功能说明 |
|---|---|
bind(address) | 将 socket 绑定到指定地址(IP 和端口) |
listen(backlog) | 开始监听连接请求(仅用于 TCP) |
accept() | 接受客户端连接,返回一个新的 socket 和客户端地址 |
scend() | 发送数据 |
recv() | 接收数据 |
import socket
if __name__ == '__main__':
# 1. 创建服务器端套接字对象
tcp_server_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 绑定IP地址和端口号(ip不写代表本机)
tcp_server_client.bind(('', 8888))
# 3. 开启监听(listen(10) 的作用就是告诉操作系统:最多允许有 10 个连接请求在排队。)
tcp_server_client.listen(10)
# 4. 接收客户端连接请求(利用拆包)
conn_socket,ip_port = tcp_server_client.accept()
print(f'客户端IP地址和端口号:{ip_port}')
# 5. 接收数据
recv_data = conn_socket.recv(1024).decode()
print(f'接收到的数据:{recv_data}')
# 6. 发送数据(.encode()将字符串转为bytes,默认编码方式就是utf-8)
conn_socket.send(f'客户端的数据已经收到了'.encode())
# 7. 关闭套接字
conn_socket.close()
tcp_server_client.close()
2.3 客户端
客户端常用方法:
| 方法名 | 功能说明 |
|---|---|
connect(address) | 连接到服务器(适用于 TCP) |
send(bytes) | 发送数据(TCP) |
recv(bufsize) | 接收数据(TCP) |
sendto(bytes, address) | 发送数据(UDP) |
recvfrom(bufsize) | 接收数据和发送方地址(UDP) |
import json
import socket
if __name__ == '__main__':
# 1. 创建客户端套接字对象
tcp_client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 2. 和服务器套接字建立连接(参数必须是一个元组)
tcp_client_socket.connect(('localhost',8888))
# 3. 发送数据
str1 = input('请输入传输信息:\n')
tcp_client_socket.send(str1.encode(encoding='utf-8'))
# 4. 接收数据
recv_data = tcp_client_socket.recv(1024).decode('utf-8')
print(recv_data)
# 5. 关闭客户端套接字
tcp_client_socket.close()
三、进程和线程基础
进程(Process) 和 线程(Thread) 是实现并发编程的两种主要方式。它们都可以用来提高程序的执行效率,但适用于不同的场景。
| 特性 | 进程(Process) | 线程(Thread) |
|---|---|---|
| 内存是否共享 | 否 | 是 |
| 资源占用 | 大 | 小 |
| 切换开销 | 高 | 低 |
| 是否受 GIL 限制 | 否(每个进程有自己的 GIL) | 是 |
| 并行能力 | 支持多核并行(CPU 密集型推荐) | 不支持真正的并行(IO 密集型推荐) |
| 稳定性 | 高(一个进程崩溃不影响其他) | 低(共享资源可能互相影响) |
| 编程复杂度 | 相对较高 | 较低 |
并发:指多个任务在逻辑上同时进行,但在物理层面可能是交替执行的。比如对于单核cpu处理多任务,操作系统轮流让各个任务交替执行 。

并行:指多个任务真正地在同一时刻执行,通常依赖于多核 CPU 或多台机器。

| 对比项 | 并发(Concurrency) | 并行(Parallelism) |
|---|---|---|
| 是否真正同时执行 | ❌ 不一定,通常是交替执行 | ✅ 真正同时执行 |
| 主要用途 | IO 密集型任务(如网络请求、文件读写) | CPU 密集型任务(如图像处理、计算) |
| 实现方式 | 单线程/多线程、事件循环 | 多进程、多线程(多核)、GPU 加速 |
| Python 示例 | threading, asyncio | multiprocessing, ProcessPoolExecutor |
| 资源占用 | 较低 | 较高 |
| 稳定性 | 可能因资源共享产生竞争条件 | 进程间隔离,更稳定 |
3.1 进程简介
进程是操作系统中资源分配的基本单位,通俗理解一个正在运行的程序就是一个进程,每个进程都有自己独立的内存空间和系统资源。由 multiprocessing 模块来创建和管理进程。

| 特性 | 描述 |
|---|---|
| 内存隔离 | 进程之间内存不共享,数据更安全 |
| 稳定性高 | 一个进程崩溃不影响其他进程 |
| 启动开销大 | 创建和销毁进程比线程慢 |
| 利用多核 | 可以利用多核 CPU 并行计算,适合 CPU 密集型任务 |
程序运行会默认创建一个进程,这个默认创建的进程我们称之为主进程

使用多进程之后会程序又创建的进程成为子进程。
基本用法:创建进程
Process(target=函数):指定进程执行的目标函数。
start():启动进程。
import multiprocessing
import time
def music():
for i in range(2):
print('听音乐...')
time.sleep(0.1)
def play():
for i in range(2):
print('打篮球...')
time.sleep(0.1)
if __name__ == '__main__':
music_prosess = multiprocessing.Process(target=music)
play_process = multiprocessing.Process(target=play)
music_prosess.start()
play_process.start()

带参数的进程: args以元组的方式给执行任务传参,kwargs以字典方式给执行任务传参。
import multiprocessing
import time
def play(num,sta_str):
print(sta_str)
for i in range(num):
print('打篮球...')
time.sleep(0.2)
def music(num):
for i in range(num):
print('rapper...')
time.sleep(0.2)
if __name__ == '__main__':
play_process = multiprocessing.Process(target=play,kwargs={'num':2,'sta_str':'多任务要开始了'})
music_prosess = multiprocessing.Process(target=music,args=(2,))
play_process.start()
music_prosess.start()
获取进程编号:当程序中进程的数量越来越多时 , 如果没有办法区分主进程和子进程还有不同的子进程 , 那么就无法进行有效的进程管理 , 为了方便管理实际上每个进程都是有自己编号的。
import multiprocessing
import time
import os
def play():
# getpid()获取当前进程(子进程)的编号
print(f'play >> {os.getpid()}')
# getppid()获取父进程的编号
print(f'play-p >> {os.getppid()}')
time.sleep(0.2)
def rap():
print(f'rap >> {os.getpid()}')
print(f'rap-p >> {os.getppid()}')
time.sleep(0.2)
if __name__ == '__main__':
print(os.getpid())
play_process = multiprocessing.Process(target=play)
play_rap = multiprocessing.Process(target=rap)
play_process.start()
play_rap.start()

进程间不共享全局变量:
import multiprocessing
import time
my_list = []
def write():
for i in range(3):
my_list.append(i)
def read():
print(my_list)
if __name__ == '__main__':
write_process = multiprocessing.Process(target=write)
read_process = multiprocessing.Process(target=read)
write_process.start()
time.sleep(1)
read_process.start() # []
print(my_list) # []
守护进程:保证主进程退出后子进程自动终止
import multiprocessing
import time
def work():
for i in range(10):
print('子进程...')
time.sleep(0.3)
if __name__ == '__main__':
work_process = multiprocessing.Process(target=work)
# 方式一
# 设置守护主进程,主进程退出后直接销毁子进程,不再执行子进程中的代码
work_process.daemon = True
work_process.start()
time.sleep(1)
# 方式二(不推荐,容易产生僵尸进程)
# 在主进程退出之前,让所有的子进程全部直接销毁掉
# work_process.terminate()
print('主进程执行完毕')
3.2 线程
线程是程序执行的最小单位, 实际上进程只负责分配资源 , 而利用这些资源执行程序的是线程 , 也就说进程是线程的容器 , 一个进程中最少有一个线程来负责执行程序 。使用 threading 模块来创建和管理线程。
| 特性 | 描述 |
|---|---|
| 共享内存 | 多个线程可以访问相同的数据 |
| 启动快 | 线程比进程轻量,启动速度快 |
| GIL限制 | Python 的全局解释器锁(GIL)使多线程不能真正并行 |
| 适合IO密集型 | 如文件读写、网络请求等 |
基本用法:创建线程
import threading
import time
def play(num):
for i in range(num):
print('打篮球...')
time.sleep(0.2)
def rap(num,str1):
print(str1)
for i in range(num):
print('rapper...')
time.sleep(0.2)
if __name__ == '__main__':
play_thread = threading.Thread(target=play,args=(3,))
rap_thread = threading.Thread(target=rap,kwargs={'num':3,'str1':'开始rap'})
play_thread.start()
rap_thread.start()
线程守护:
import threading
import time
""" 主线程默认等子线程运行结束后才终止 """
def work():
for i in range(10):
print('工作中...')
time.sleep(0.2)
if __name__ == '__main__':
# 方式一,创建子线程并设置守护主线程
# work_thread = threading.Thread(target=work,daemon=True)
work_thread = threading.Thread(target=work)
# 方式二,设置守护主线程
work_thread.daemon = True
work_thread.start()
time.sleep(1)
print('主线程运行结束')
线程执行顺序:线程之间的执行是无序的,由CPU调度决定某个线程先执行
import threading
import time
def work():
time.sleep(0.5)
current_thread = threading.current_thread()
print(current_thread)
if __name__ == '__main__':
for i in range(10):
work_thread = threading.Thread(target=work)
work_thread.start()

线程间共享全局变量:多个线程都是在同一个进程中 , 多个线程使用的资源都是同一个进程中的资源 ,因此多线程间是共享全局变量
import threading
import time
list1 = []
def write():
for i in range(3):
list1.append(i)
def read():
print(list1)
if __name__ == '__main__':
write_thread = threading.Thread(target=write)
read_thread = threading.Thread(target=read)
write_thread.start()
time.sleep(1)
read_thread.start() # [0, 1, 2]
print(list1) # [0, 1, 2]
互斥锁:
1. 创建互斥锁
lock = threading.Lock()
2. 上锁
lock.acquire()
3. 释放锁
lock.release()
注意:如果加锁之后没有在合适的地方释放锁会形成死锁。
import threading
lock = threading.Lock() # 创建一个锁对象,用于线程同步
sum = 0# 全局变量,用于累加计数
def play(num):
global sum
for i in range(num):
lock.acquire() # 加锁,防止多个线程同时修改sum
sum += 1 # 修改共享资源(sum)的代码段
lock.release() # 释放锁
print(f"{sum}---------打篮球----------")
def rap(num):
global sum
for i in range(num):
lock.acquire()
sum += 1
lock.release()
print(f"{sum}----------rapper----------")
if __name__ == '__main__':
thread_s1 = threading.Thread(target=play,args=(1000000,))
thread_Stu = threading.Thread(target=rap,args=(1000000,))
thread_s1.start()
thread_Stu.start()
上面代码如果不加锁的话低版本Python解释器会出现争抢资源的问题。

2192





